diff --git a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java index 7694754de6ff1eab73769b96689431612ab3701c..c9ffdae890c5e753e06f35836934f5ab69aa69b1 100644 --- a/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java +++ b/core/java/android/view/inputmethod/RemoteInputConnectionImpl.java @@ -49,7 +49,6 @@ import android.view.KeyEvent; import android.view.View; import android.view.ViewRootImpl; -import com.android.internal.annotations.GuardedBy; import com.android.internal.infra.AndroidFuture; import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; import com.android.internal.inputmethod.IRemoteInputConnection; @@ -60,6 +59,7 @@ import java.lang.annotation.Retention; import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.util.function.Supplier; @@ -164,18 +164,15 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { boolean cancellable(); } - @GuardedBy("mLock") - @Nullable - private InputConnection mInputConnection; + @NonNull + private final AtomicReference<InputConnection> mInputConnectionRef; + @NonNull + private final AtomicBoolean mDeactivateRequested = new AtomicBoolean(false); @NonNull private final Looper mLooper; private final Handler mH; - private final Object mLock = new Object(); - @GuardedBy("mLock") - private boolean mFinished = false; - private final InputMethodManager mParentInputMethodManager; private final WeakReference<View> mServedView; @@ -193,7 +190,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { RemoteInputConnectionImpl(@NonNull Looper looper, @NonNull InputConnection inputConnection, @NonNull InputMethodManager inputMethodManager, @Nullable View servedView) { - mInputConnection = inputConnection; + mInputConnectionRef = new AtomicReference<>(inputConnection); mLooper = looper; mH = new Handler(mLooper); mParentInputMethodManager = inputMethodManager; @@ -211,9 +208,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { */ @Nullable public InputConnection getInputConnection() { - synchronized (mLock) { - return mInputConnection; - } + return mInputConnectionRef.get(); } /** @@ -229,13 +224,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { * {@link InputConnection#closeConnection()} as a result of {@link #deactivate()}. */ private boolean isFinished() { - synchronized (mLock) { - return mFinished; - } - } - - private boolean isActive() { - return mParentInputMethodManager.isActive() && !isFinished(); + return mInputConnectionRef.get() == null; } private View getServedView() { @@ -372,28 +361,18 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { */ @Dispatching(cancellable = false) public void deactivate() { - if (isFinished()) { + if (mDeactivateRequested.getAndSet(true)) { // This is a small performance optimization. Still only the 1st call of - // reportFinish() will take effect. + // deactivate() will take effect. return; } dispatch(() -> { // Deactivate the notifier when finishing typing. notifyTypingHint(false /* isTyping */, true /* deactivate */); - // 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 closeConnection() tasks will not be handled at the same time. - if (isFinished()) { - return; - } Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#closeConnection"); try { InputConnection ic = getInputConnection(); - // 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; } @@ -403,10 +382,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { // TODO(b/199934664): See if we can remove this by providing a default impl. } } finally { - synchronized (mLock) { - mInputConnection = null; - mFinished = true; - } + mInputConnectionRef.set(null); Trace.traceEnd(Trace.TRACE_TAG_INPUT); } @@ -460,8 +436,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { public String toString() { return "RemoteInputConnectionImpl{" + "connection=" + getInputConnection() - + " finished=" + isFinished() - + " mParentInputMethodManager.isActive()=" + mParentInputMethodManager.isActive() + + " mDeactivateRequested=" + mDeactivateRequested.get() + " mServedView=" + mServedView.get() + "}"; } @@ -474,16 +449,14 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { * {@link DumpableInputConnection#dumpDebug(ProtoOutputStream, long)}. */ public void dumpDebug(ProtoOutputStream proto, long fieldId) { - synchronized (mLock) { - // Check that the call is initiated in the target thread of the current InputConnection - // {@link InputConnection#getHandler} since the messages to IInputConnectionWrapper are - // executed on this thread. Otherwise the messages are dispatched to the correct thread - // in IInputConnectionWrapper, but this is not wanted while dumpng, for performance - // reasons. - if ((mInputConnection instanceof DumpableInputConnection) - && mLooper.isCurrentThread()) { - ((DumpableInputConnection) mInputConnection).dumpDebug(proto, fieldId); - } + final InputConnection ic = mInputConnectionRef.get(); + // Check that the call is initiated in the target thread of the current InputConnection + // {@link InputConnection#getHandler} since the messages to IInputConnectionWrapper are + // executed on this thread. Otherwise the messages are dispatched to the correct thread + // in IInputConnectionWrapper, but this is not wanted while dumping, for performance + // reasons. + if ((ic instanceof DumpableInputConnection) && mLooper.isCurrentThread()) { + ((DumpableInputConnection) ic).dumpDebug(proto, fieldId); } } @@ -498,7 +471,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { public void dispatchReportFullscreenMode(boolean enabled) { dispatch(() -> { final InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { return; } ic.reportFullscreenMode(enabled); @@ -514,7 +487,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return null; // cancelled } final InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "getTextAfterCursor on inactive InputConnection"); return null; } @@ -536,7 +509,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return null; // cancelled } final InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "getTextBeforeCursor on inactive InputConnection"); return null; } @@ -558,7 +531,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return null; // cancelled } final InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "getSelectedText on inactive InputConnection"); return null; } @@ -580,7 +553,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return null; // cancelled } final InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "getSurroundingText on inactive InputConnection"); return null; } @@ -608,7 +581,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return 0; // cancelled } final InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "getCursorCapsMode on inactive InputConnection"); return 0; } @@ -625,7 +598,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return null; // cancelled } final InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "getExtractedText on inactive InputConnection"); return null; } @@ -642,7 +615,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "commitText on inactive InputConnection"); return; } @@ -660,7 +633,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "commitText on inactive InputConnection"); return; } @@ -676,7 +649,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "commitCompletion on inactive InputConnection"); return; } @@ -692,7 +665,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "commitCorrection on inactive InputConnection"); return; } @@ -712,7 +685,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "setSelection on inactive InputConnection"); return; } @@ -728,7 +701,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "performEditorAction on inactive InputConnection"); return; } @@ -744,7 +717,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "performContextMenuAction on inactive InputConnection"); return; } @@ -760,7 +733,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "setComposingRegion on inactive InputConnection"); return; } @@ -781,7 +754,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "setComposingRegion on inactive InputConnection"); return; } @@ -798,7 +771,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "setComposingText on inactive InputConnection"); return; } @@ -816,7 +789,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "setComposingText on inactive InputConnection"); return; } @@ -845,11 +818,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - // 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) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "finishComposingTextFromImm on inactive InputConnection"); return; } @@ -873,11 +842,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - // 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) { + if (ic == null && mDeactivateRequested.get()) { Log.w(TAG, "finishComposingText on inactive InputConnection"); return; } @@ -893,7 +858,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "sendKeyEvent on inactive InputConnection"); return; } @@ -909,7 +874,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "clearMetaKeyStates on inactive InputConnection"); return; } @@ -926,7 +891,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "deleteSurroundingText on inactive InputConnection"); return; } @@ -944,7 +909,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection"); return; } @@ -964,7 +929,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "beginBatchEdit on inactive InputConnection"); return; } @@ -980,7 +945,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "endBatchEdit on inactive InputConnection"); return; } @@ -996,7 +961,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "performSpellCheck on inactive InputConnection"); return; } @@ -1013,7 +978,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "performPrivateCommand on inactive InputConnection"); return; } @@ -1051,7 +1016,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "performHandwritingGesture on inactive InputConnection"); if (resultReceiver != null) { resultReceiver.send( @@ -1091,7 +1056,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "previewHandwritingGesture on inactive InputConnection"); return; // cancelled } @@ -1139,7 +1104,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { @InputConnection.CursorUpdateMode int cursorUpdateMode, @InputConnection.CursorUpdateFilter int cursorUpdateFilter, int imeDisplayId) { final InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "requestCursorUpdates on inactive InputConnection"); return false; } @@ -1177,7 +1142,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "requestTextBoundsInfo on inactive InputConnection"); resultReceiver.send(TextBoundsInfoResult.CODE_CANCELLED, null); return; @@ -1221,7 +1186,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return false; // cancelled } final InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "commitContent on inactive InputConnection"); return false; } @@ -1246,7 +1211,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "setImeConsumesInput on inactive InputConnection"); return; } @@ -1270,7 +1235,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "replaceText on inactive InputConnection"); return; } @@ -1289,7 +1254,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "commitText on inactive InputConnection"); return; } @@ -1309,7 +1274,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "setSelection on inactive InputConnection"); return; } @@ -1326,7 +1291,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return null; // cancelled } final InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "getSurroundingText on inactive InputConnection"); return null; } @@ -1354,7 +1319,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "deleteSurroundingText on inactive InputConnection"); return; } @@ -1370,7 +1335,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "sendKeyEvent on inactive InputConnection"); return; } @@ -1386,7 +1351,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "performEditorAction on inactive InputConnection"); return; } @@ -1402,7 +1367,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "performContextMenuAction on inactive InputConnection"); return; } @@ -1419,7 +1384,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return 0; // cancelled } final InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "getCursorCapsMode on inactive InputConnection"); return 0; } @@ -1435,7 +1400,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub { return; // cancelled } InputConnection ic = getInputConnection(); - if (ic == null || !isActive()) { + if (ic == null || mDeactivateRequested.get()) { Log.w(TAG, "clearMetaKeyStates on inactive InputConnection"); return; }