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

Commit a6a219e6 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix some thread handling issues in InputMethodManager"

parents d9dbcb35 3f733cc7
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ public final class ImeFocusController {
    private boolean mHasImeFocus = false;
    private View mServedView;
    private View mNextServedView;
    private InputMethodManagerDelegate mDelegate;

    @UiThread
    ImeFocusController(@NonNull ViewRootImpl viewRootImpl) {
@@ -45,7 +46,11 @@ public final class ImeFocusController {
    }

    private InputMethodManagerDelegate getImmDelegate() {
        return mViewRootImpl.mContext.getSystemService(InputMethodManager.class).getDelegate();
        if (mDelegate == null) {
            mDelegate = mViewRootImpl.mContext.getSystemService(
                    InputMethodManager.class).getDelegate();
        }
        return mDelegate;
    }

    @UiThread
+48 −22
Original line number Diff line number Diff line
@@ -59,12 +59,12 @@ import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.SparseArray;
import android.view.Display;
import android.view.ImeFocusController;
import android.view.ImeInsetsSourceConsumer;
import android.view.InputChannel;
import android.view.InputEvent;
import android.view.InputEventSender;
import android.view.KeyEvent;
import android.view.ImeFocusController;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
@@ -562,15 +562,24 @@ public final class InputMethodManager {
        public boolean startInput(@StartInputReason int startInputReason, View focusedView,
                @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode,
                int windowFlags) {
            final View servedView;
            synchronized (mH) {
                mCurrentTextBoxAttribute = null;
                mCompletions = null;
                mServedConnecting = true;
                if (getServedViewLocked() != null && !getServedViewLocked().onCheckIsTextEditor()) {
                servedView = getServedViewLocked();
            }
            if (servedView != null && servedView.getHandler() != null) {
                // Make sure View checks should be on the UI thread.
                servedView.getHandler().post(() -> {
                    if (!servedView.onCheckIsTextEditor()) {
                        // servedView has changed and it's not editable.
                        synchronized (mH) {
                            maybeCallServedViewChangedLocked(null);
                        }
                    }
                });
            }
            return startInputInner(startInputReason,
                    focusedView != null ? focusedView.getWindowToken() : null, startInputFlags,
                    softInputMode, windowFlags);
@@ -607,11 +616,11 @@ public final class InputMethodManager {
                mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */);
            }
            mWindowFocusGainFuture = mStartInputWorker.submit(() -> {
                synchronized (mH) {
                    if (mCurRootView == null) {
                final ImeFocusController controller = getFocusController();
                if (controller == null) {
                    return;
                }
                    if (mCurRootView.getImeFocusController().checkFocus(forceNewFocus1, false)) {
                if (controller.checkFocus(forceNewFocus1, false)) {
                    // We need to restart input on the current focus view.  This
                    // should be done in conjunction with telling the system service
                    // about the window gaining focus, to help make the transition
@@ -622,6 +631,7 @@ public final class InputMethodManager {
                    }
                }

                synchronized (mH) {
                    // For some reason we didn't do a startInput + windowFocusGain, so
                    // we'll just do a window focus gain and call it a day.
                    try {
@@ -716,6 +726,15 @@ public final class InputMethodManager {
        }
    }

    private ImeFocusController getFocusController() {
        synchronized (mH) {
            if (mCurRootView != null) {
                return mCurRootView.getImeFocusController();
            }
            return null;
        }
    }

    /**
     * Returns {@code true} when the given view has been served by Input Method.
     */
@@ -1793,6 +1812,12 @@ public final class InputMethodManager {
        startInputInner(StartInputReason.APP_CALLED_RESTART_INPUT_API, null, 0, 0, 0);
    }

    /**
     * Called when {@link DelegateImpl#startInput}, {@link #restartInput(View)},
     * {@link #MSG_BIND} or {@link #MSG_UNBIND}.
     * Note that this method should *NOT* be called inside of {@code mH} lock to prevent start input
     * background thread may blocked by other methods which already inside {@code mH} lock.
     */
    boolean startInputInner(@StartInputReason int startInputReason,
            @Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags,
            @SoftInputModeFlags int softInputMode, int windowFlags) {
@@ -1976,15 +2001,16 @@ public final class InputMethodManager {
    }

    /**
     * Check the next served view from {@link ImeFocusController} if needs to start input.
     * Note that this method should *NOT* be called inside of {@code mH} lock to prevent start input
     * background thread may blocked by other methods which already inside {@code mH} lock.
     * @hide
     */
    @UnsupportedAppUsage
    public void checkFocus() {
        synchronized (mH) {
            if (mCurRootView != null) {
                mCurRootView.getImeFocusController().checkFocus(false /* forceNewFocus */,
                        true /* startInput */);
            }
        final ImeFocusController controller = getFocusController();
        if (controller != null) {
            controller.checkFocus(false /* forceNewFocus */, true /* startInput */);
        }
    }