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

Commit 3d41d2b6 authored by Wilson Wu's avatar Wilson Wu
Browse files

Ensure onTypingHintChanged run on UiThread

RemoteInputConnectionImpl can be run on a different
thread. Dispatch onTypingHintChanged operation with the
ViewRootImpl's handler to ensure it runs on the UiThread.

Bug: 281720315
Test: presubmit
Merged-In: I2fb9c549da19ff01e7cc3fd8bfc1f9c19aa0f0a8
Change-Id: I45376816cf01065e270dc1a8e2f3d1d3e564e9cd
parent 2e5c0b58
Loading
Loading
Loading
Loading
+33 −12
Original line number Diff line number Diff line
@@ -434,15 +434,15 @@ public final class ViewRootImpl implements ViewParent,
        /**
         * Called when the typing hint is changed. This would be invoked by the
         * {@link android.view.inputmethod.RemoteInputConnectionImpl}
         * to hint if the user is typing when the it is {@link #isActive() active}.
         * to hint if the user is typing when it is {@link #isActive() active}.
         *
         * This can be only happened on the UI thread. The behavior won't be guaranteed if
         * invoking this on a non-UI thread.
         * The operation in this method should be dispatched to the UI thread to
         * keep the sequence.
         *
         * @param isTyping {@code true} if the user is typing.
         * @param deactivate {code true} if the input connection deactivate
         */
        @UiThread
        void onTypingHintChanged(boolean isTyping);
        void onTypingHintChanged(boolean isTyping, boolean deactivate);

        /**
         * Indicates whether the notifier is currently in active state or not.
@@ -468,19 +468,40 @@ public final class ViewRootImpl implements ViewParent,
        @NonNull
        private final ViewRootRefreshRateController mController;

        @NonNull
        private final Handler mHandler;

        @NonNull
        private final Thread mThread;

        TypingHintNotifierImpl(@NonNull AtomicReference<TypingHintNotifier> notifier,
                @NonNull ViewRootRefreshRateController controller) {
                @NonNull ViewRootRefreshRateController controller, @NonNull Handler handler,
                @NonNull Thread thread) {
            mController = controller;
            mActiveNotifier = notifier;
            mHandler = handler;
            mThread = thread;
        }

        @Override
        public void onTypingHintChanged(boolean isTyping) {
        public void onTypingHintChanged(boolean isTyping, boolean deactivate) {
            final Runnable runnable = () -> {
                if (!isActive()) {
                    // No-op when the listener was deactivated.
                    return;
                }
                mController.updateRefreshRatePreference(isTyping ? LOWER : RESTORE);
                if (deactivate) {
                    deactivate();
                }
            };

            if (Thread.currentThread() == mThread) {
                // Run directly if it's on the UiThread.
                runnable.run();
            } else {
                mHandler.post(runnable);
            }
        }

        @Override
@@ -521,7 +542,7 @@ public final class ViewRootImpl implements ViewParent,
            return null;
        }
        final TypingHintNotifier newNotifier = new TypingHintNotifierImpl(mActiveTypingHintNotifier,
                mRefreshRateController);
                mRefreshRateController, mHandler, mThread);
        mActiveTypingHintNotifier.set(newNotifier);

        return newNotifier;
+6 −11
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.graphics.RectF;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -373,11 +372,8 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
            return;
        }
        dispatch(() -> {
            notifyTypingHint(false /* isTyping */);
            // Deactivate the notifier when finishing typing.
            if (mTypingHintNotifier != null) {
                mTypingHintNotifier.deactivate();
            }
            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
@@ -643,7 +639,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
                return;
            }
            ic.commitText(text, newCursorPosition);
            notifyTypingHint(true /* isTyping */);
            notifyTypingHint(true /* isTyping */, false /* deactivate */);
        });
    }

@@ -799,7 +795,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
                return;
            }
            ic.setComposingText(text, newCursorPosition);
            notifyTypingHint(true /* isTyping */);
            notifyTypingHint(true /* isTyping */, false /* deactivate */);
        });
    }

@@ -927,7 +923,7 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
                return;
            }
            ic.deleteSurroundingText(beforeLength, afterLength);
            notifyTypingHint(true /* isTyping */);
            notifyTypingHint(true /* isTyping */, false /* deactivate */);
        });
    }

@@ -1497,10 +1493,9 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
     * The input connection indicates that the user is typing when {@link #commitText} or
     * {@link #setComposingText)} and the user finish typing when {@link #deactivate()}.
     */
    @UiThread
    private void notifyTypingHint(boolean isTyping) {
    private void notifyTypingHint(boolean isTyping, boolean deactivate) {
        if (mTypingHintNotifier != null) {
            mTypingHintNotifier.onTypingHintChanged(isTyping);
            mTypingHintNotifier.onTypingHintChanged(isTyping, deactivate);
        }
    }
}