Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e37d17eb authored by Taran Singh's avatar Taran Singh Committed by Android (Google) Code Review
Browse files

Merge changes I4ff71de0,I545bbac0 into main

* changes:
  Add flag to fix race for invalidate/restart input
  Log invalid sessionId in InputConnection operations
parents c2bbff6f b62d5184
Loading
Loading
Loading
Loading
+101 −87
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UiThread;
import android.app.UriGrantsManager;
import android.content.ContentProvider;
import android.content.Intent;
@@ -38,6 +37,7 @@ import android.os.Binder;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.CancellationSignalBeamer;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -468,13 +468,27 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
        });
    }

    /**
     * Returns {@code false} if there is a sessionId mismatch and logs the event.
     */
    private boolean checkSessionId(@NonNull InputConnectionCommandHeader header) {
        if (header.mSessionId != mCurrentSessionId.get()) {
            Log.w(TAG, "Session id mismatch header.sessionId: " + header.mSessionId
                            + " currentSessionId: " + mCurrentSessionId.get() + " while calling "
                    + Debug.getCaller());
            //TODO(b/396066692): log metrics.
            return false;  // cancelled
        }
        return true;
    }

    @Dispatching(cancellable = true)
    @Override
    public void getTextAfterCursor(InputConnectionCommandHeader header, int length, int flags,
            AndroidFuture future /* T=CharSequence */) {
        dispatchWithTracing("getTextAfterCursor", future, () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return null;  // cancelled
            if (!checkSessionId(header)) {
                return null;
            }
            final InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -495,8 +509,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void getTextBeforeCursor(InputConnectionCommandHeader header, int length, int flags,
            AndroidFuture future /* T=CharSequence */) {
        dispatchWithTracing("getTextBeforeCursor", future, () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return null;  // cancelled
            if (!checkSessionId(header)) {
                return null;
            }
            final InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -517,8 +531,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void getSelectedText(InputConnectionCommandHeader header, int flags,
            AndroidFuture future /* T=CharSequence */) {
        dispatchWithTracing("getSelectedText", future, () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return null;  // cancelled
            if (!checkSessionId(header)) {
                return null;
            }
            final InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -539,8 +553,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void getSurroundingText(InputConnectionCommandHeader header, int beforeLength,
            int afterLength, int flags, AndroidFuture future /* T=SurroundingText */) {
        dispatchWithTracing("getSurroundingText", future, () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return null;  // cancelled
            if (!checkSessionId(header)) {
                return null;
            }
            final InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -567,8 +581,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void getCursorCapsMode(InputConnectionCommandHeader header, int reqModes,
            AndroidFuture future /* T=Integer */) {
        dispatchWithTracing("getCursorCapsMode", future, () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return 0;  // cancelled
            if (!checkSessionId(header)) {
                return 0;
            }
            final InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -584,8 +598,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void getExtractedText(InputConnectionCommandHeader header, ExtractedTextRequest request,
            int flags, AndroidFuture future /* T=ExtractedText */) {
        dispatchWithTracing("getExtractedText", future, () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return null;  // cancelled
            if (!checkSessionId(header)) {
                return null;
            }
            final InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -601,8 +615,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void commitText(InputConnectionCommandHeader header, CharSequence text,
            int newCursorPosition) {
        dispatchWithTracing("commitText", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return;
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -618,7 +632,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void commitTextWithTextAttribute(InputConnectionCommandHeader header, CharSequence text,
            int newCursorPosition, @Nullable TextAttribute textAttribute) {
        dispatchWithTracing("commitTextWithTextAttribute", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
            if (!checkSessionId(header)) {
                return; // cancelled
            }
            InputConnection ic = getInputConnection();
@@ -634,7 +648,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    @Override
    public void commitCompletion(InputConnectionCommandHeader header, CompletionInfo text) {
        dispatchWithTracing("commitCompletion", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
            if (!checkSessionId(header)) {
                return; // cancelled
            }
            InputConnection ic = getInputConnection();
@@ -650,7 +664,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    @Override
    public void commitCorrection(InputConnectionCommandHeader header, CorrectionInfo info) {
        dispatchWithTracing("commitCorrection", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
            if (!checkSessionId(header)) {
                return; // cancelled
            }
            InputConnection ic = getInputConnection();
@@ -670,8 +684,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    @Override
    public void setSelection(InputConnectionCommandHeader header, int start, int end) {
        dispatchWithTracing("setSelection", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -686,8 +700,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    @Override
    public void performEditorAction(InputConnectionCommandHeader header, int id) {
        dispatchWithTracing("performEditorAction", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -702,8 +716,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    @Override
    public void performContextMenuAction(InputConnectionCommandHeader header, int id) {
        dispatchWithTracing("performContextMenuAction", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -718,8 +732,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    @Override
    public void setComposingRegion(InputConnectionCommandHeader header, int start, int end) {
        dispatchWithTracing("setComposingRegion", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -739,8 +753,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void setComposingRegionWithTextAttribute(InputConnectionCommandHeader header, int start,
            int end, @Nullable TextAttribute textAttribute) {
        dispatchWithTracing("setComposingRegionWithTextAttribute", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -756,8 +770,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void setComposingText(InputConnectionCommandHeader header, CharSequence text,
            int newCursorPosition) {
        dispatchWithTracing("setComposingText", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -773,8 +787,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void setComposingTextWithTextAttribute(InputConnectionCommandHeader header,
            CharSequence text, int newCursorPosition, @Nullable TextAttribute textAttribute) {
        dispatchWithTracing("setComposingTextWithTextAttribute", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -826,8 +840,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
                }
                return;
            }
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null && mDeactivateRequested.get()) {
@@ -842,8 +856,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    @Override
    public void sendKeyEvent(InputConnectionCommandHeader header, KeyEvent event) {
        dispatchWithTracing("sendKeyEvent", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -858,8 +872,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    @Override
    public void clearMetaKeyStates(InputConnectionCommandHeader header, int states) {
        dispatchWithTracing("clearMetaKeyStates", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -875,8 +889,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void deleteSurroundingText(InputConnectionCommandHeader header, int beforeLength,
            int afterLength) {
        dispatchWithTracing("deleteSurroundingText", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -892,8 +906,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void deleteSurroundingTextInCodePoints(InputConnectionCommandHeader header,
            int beforeLength, int afterLength) {
        dispatchWithTracing("deleteSurroundingTextInCodePoints", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -912,8 +926,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    @Override
    public void beginBatchEdit(InputConnectionCommandHeader header) {
        dispatchWithTracing("beginBatchEdit", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -928,8 +942,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    @Override
    public void endBatchEdit(InputConnectionCommandHeader header) {
        dispatchWithTracing("endBatchEdit", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -944,8 +958,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    @Override
    public void performSpellCheck(InputConnectionCommandHeader header) {
        dispatchWithTracing("performSpellCheck", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -961,8 +975,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void performPrivateCommand(InputConnectionCommandHeader header, String action,
            Bundle data) {
        dispatchWithTracing("performPrivateCommand", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -995,7 +1009,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
            }
        }
        dispatchWithTracing("performHandwritingGesture", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
            if (!checkSessionId(header)) {
                if (resultReceiver != null) {
                    resultReceiver.send(
                            InputConnection.HANDWRITING_GESTURE_RESULT_CANCELLED, null);
@@ -1038,7 +1052,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
                (PreviewableHandwritingGesture) gestureContainer.get();

        dispatchWithTracing("previewHandwritingGesture", () -> {
            if (header.mSessionId != mCurrentSessionId.get()
            if (!checkSessionId(header)
                    || (cancellationSignal != null && cancellationSignal.isCanceled())) {
                return; // cancelled
            }
@@ -1065,8 +1079,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    public void requestCursorUpdates(InputConnectionCommandHeader header, int cursorUpdateMode,
            int imeDisplayId, AndroidFuture future /* T=Boolean */) {
        dispatchWithTracing("requestCursorUpdates", future, () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return false;  // cancelled
            if (!checkSessionId(header)) {
                return false; // cancelled.
            }
            return requestCursorUpdatesInternal(
                    cursorUpdateMode, 0 /* cursorUpdateFilter */, imeDisplayId);
@@ -1079,8 +1093,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
            int cursorUpdateMode, int cursorUpdateFilter, int imeDisplayId,
            AndroidFuture future /* T=Boolean */) {
        dispatchWithTracing("requestCursorUpdates", future, () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return false;  // cancelled
            if (!checkSessionId(header)) {
                return false; // cancelled.
            }
            return requestCursorUpdatesInternal(
                    cursorUpdateMode, cursorUpdateFilter, imeDisplayId);
@@ -1123,7 +1137,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
            InputConnectionCommandHeader header, RectF bounds,
            @NonNull ResultReceiver resultReceiver) {
        dispatchWithTracing("requestTextBoundsInfo", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
            if (!checkSessionId(header)) {
                resultReceiver.send(TextBoundsInfoResult.CODE_CANCELLED, null);
                return; // cancelled
            }
@@ -1168,8 +1182,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
                return false;
            }

            if (header.mSessionId != mCurrentSessionId.get()) {
                return false;  // cancelled
            if (!checkSessionId(header)) {
                return false; // cancelled.
            }
            final InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -1193,8 +1207,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
    @Override
    public void setImeConsumesInput(InputConnectionCommandHeader header, boolean imeConsumesInput) {
        dispatchWithTracing("setImeConsumesInput", () -> {
            if (header.mSessionId != mCurrentSessionId.get()) {
                return;  // cancelled
            if (!checkSessionId(header)) {
                return; // cancelled.
            }
            InputConnection ic = getInputConnection();
            if (ic == null || mDeactivateRequested.get()) {
@@ -1217,8 +1231,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
        dispatchWithTracing(
                "replaceText",
                () -> {
                    if (header.mSessionId != mCurrentSessionId.get()) {
                        return; // cancelled
                    if (!checkSessionId(header)) {
                        return; // cancelled.
                    }
                    InputConnection ic = getInputConnection();
                    if (ic == null || mDeactivateRequested.get()) {
@@ -1236,8 +1250,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
        public void commitText(InputConnectionCommandHeader header, CharSequence text,
                int newCursorPosition, @Nullable TextAttribute textAttribute) {
            dispatchWithTracing("commitTextFromA11yIme", () -> {
                if (header.mSessionId != mCurrentSessionId.get()) {
                    return;  // cancelled
                if (!checkSessionId(header)) {
                    return; // cancelled.
                }
                InputConnection ic = getInputConnection();
                if (ic == null || mDeactivateRequested.get()) {
@@ -1256,8 +1270,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
        @Override
        public void setSelection(InputConnectionCommandHeader header, int start, int end) {
            dispatchWithTracing("setSelectionFromA11yIme", () -> {
                if (header.mSessionId != mCurrentSessionId.get()) {
                    return;  // cancelled
                if (!checkSessionId(header)) {
                    return; // cancelled.
                }
                InputConnection ic = getInputConnection();
                if (ic == null || mDeactivateRequested.get()) {
@@ -1273,8 +1287,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
        public void getSurroundingText(InputConnectionCommandHeader header, int beforeLength,
                int afterLength, int flags, AndroidFuture future /* T=SurroundingText */) {
            dispatchWithTracing("getSurroundingTextFromA11yIme", future, () -> {
                if (header.mSessionId != mCurrentSessionId.get()) {
                    return null;  // cancelled
                if (!checkSessionId(header)) {
                    return null; // cancelled.
                }
                final InputConnection ic = getInputConnection();
                if (ic == null || mDeactivateRequested.get()) {
@@ -1301,8 +1315,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
        public void deleteSurroundingText(InputConnectionCommandHeader header, int beforeLength,
                int afterLength) {
            dispatchWithTracing("deleteSurroundingTextFromA11yIme", () -> {
                if (header.mSessionId != mCurrentSessionId.get()) {
                    return;  // cancelled
                if (!checkSessionId(header)) {
                    return; // cancelled.
                }
                InputConnection ic = getInputConnection();
                if (ic == null || mDeactivateRequested.get()) {
@@ -1317,8 +1331,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
        @Override
        public void sendKeyEvent(InputConnectionCommandHeader header, KeyEvent event) {
            dispatchWithTracing("sendKeyEventFromA11yIme", () -> {
                if (header.mSessionId != mCurrentSessionId.get()) {
                    return;  // cancelled
                if (!checkSessionId(header)) {
                    return; // cancelled.
                }
                InputConnection ic = getInputConnection();
                if (ic == null || mDeactivateRequested.get()) {
@@ -1333,8 +1347,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
        @Override
        public void performEditorAction(InputConnectionCommandHeader header, int id) {
            dispatchWithTracing("performEditorActionFromA11yIme", () -> {
                if (header.mSessionId != mCurrentSessionId.get()) {
                    return;  // cancelled
                if (!checkSessionId(header)) {
                    return; // cancelled.
                }
                InputConnection ic = getInputConnection();
                if (ic == null || mDeactivateRequested.get()) {
@@ -1349,8 +1363,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
        @Override
        public void performContextMenuAction(InputConnectionCommandHeader header, int id) {
            dispatchWithTracing("performContextMenuActionFromA11yIme", () -> {
                if (header.mSessionId != mCurrentSessionId.get()) {
                    return;  // cancelled
                if (!checkSessionId(header)) {
                    return; // cancelled.
                }
                InputConnection ic = getInputConnection();
                if (ic == null || mDeactivateRequested.get()) {
@@ -1366,8 +1380,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
        public void getCursorCapsMode(InputConnectionCommandHeader header, int reqModes,
                AndroidFuture future /* T=Integer */) {
            dispatchWithTracing("getCursorCapsModeFromA11yIme", future, () -> {
                if (header.mSessionId != mCurrentSessionId.get()) {
                    return 0;  // cancelled
                if (!checkSessionId(header)) {
                    return 0; // cancelled.
                }
                final InputConnection ic = getInputConnection();
                if (ic == null || mDeactivateRequested.get()) {
@@ -1382,8 +1396,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
        @Override
        public void clearMetaKeyStates(InputConnectionCommandHeader header, int states) {
            dispatchWithTracing("clearMetaKeyStatesFromA11yIme", () -> {
                if (header.mSessionId != mCurrentSessionId.get()) {
                    return;  // cancelled
                if (!checkSessionId(header)) {
                    return; // cancelled.
                }
                InputConnection ic = getInputConnection();
                if (ic == null || mDeactivateRequested.get()) {
+10 −0
Original line number Diff line number Diff line
@@ -214,3 +214,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
  name: "invalidate_input_calls_restart"
  namespace: "input_method"
  description: "Feature flag to fix the race between invalidateInput and restartInput"
  bug: "396066692"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}