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

Commit 0df88124 authored by lumark's avatar lumark Committed by Ming-Shin Lu
Browse files

Finish input when the screen state is off

Add ImeFocusController#onScreenStateChanged callback for ViewRootImpl to
callback the screen state for ImeFocusController, and then check the served
view to finish input connection when the screen state is off.

With this change, we can remove InputMethodManagerService#setInteractive
related codes, since we still can finish current input connection
once the device is screen off, ensures the security behavior remains
the same.

This change is expected to reduce accumulated technical debt introduced
by [Prior works] to address multiple edge cases [1][2][3][4], especially
around window focus changes and display-off events.

[Prior works]
 [1]. Re-start input when the IME is deactivated but window is focused
        (Bug 6188159)
          I9189e6d2ac90aa8c621fdb44989728101e00329d
          31e4e149
 [2]. Fix a crash in InputMethodManager when switching the IME in the
      system process
        (Bug  6789252)
          I66f51da1299532793ef8fa700f35b0811670f235
          4e5184f9
 [3]. Call startInput on return from sleep mode
        (Bug 17558972)
          I95d05110bc1cf310fad23ea1bcbc5890f642d1fc
          82ae3ff4
 [4]. Make IMM more robust to spurious window focus-in
        (Bug 26851566)
          I60adb38013b063918b074c7b947649eada77b2c8
          8e9214b4

Note that one behavior change is that when the screen is on and window focus
back to the app, if the app previously did't request show soft input explictly,
InputMethodManager will not request to show soft-keyboard explicitly for the
next served view.

Fix: 26851566
Bug: 141738570
Bug: 9216494

Test: atest SearchViewTest, FocusHandlingTest
Test: atest ActivityViewTest, MultiDisplayClientTests,
      MultiDisplaySystemDecorationTests

Change-Id: Ic11956fe745a829da1ec7c09ea214e9b3961c8e0
parent a72d7e53
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -196,6 +196,26 @@ public final class ImeFocusController {
        mHasImeFocus = false;
    }

    /**
     * Called by {@link ViewRootImpl} to feedback the state of the screen for this view.
     * @param newScreenState The new state of the screen. Can be either
     *                       {@link View#SCREEN_STATE_ON} or {@link View#SCREEN_STATE_OFF}
     */
    @UiThread
    void onScreenStateChanged(int newScreenState) {
        if (!getImmDelegate().isCurrentRootView(mViewRootImpl)) {
            return;
        }
        // Close input connection and IME when the screen is turn off for security concern.
        if (newScreenState == View.SCREEN_STATE_OFF && mServedView != null) {
            if (DEBUG) {
                Log.d(TAG, "onScreenStateChanged, disconnect input when screen turned off");
            }
            mNextServedView = null;
            mViewRootImpl.dispatchCheckFocus();
        }
    }

    /**
     * @param windowAttribute {@link WindowManager.LayoutParams} to be checked.
     * @return Whether the window is in local focus mode or not.
+1 −0
Original line number Diff line number Diff line
@@ -1445,6 +1445,7 @@ public final class ViewRootImpl implements ViewParent,
                        final int newScreenState = toViewScreenState(newDisplayState);
                        if (oldScreenState != newScreenState) {
                            mView.dispatchScreenStateChanged(newScreenState);
                            mImeFocusController.onScreenStateChanged(newScreenState);
                        }
                        if (oldDisplayState == Display.STATE_OFF) {
                            // Draw was suppressed so we need to for it to happen here.
+0 −10
Original line number Diff line number Diff line
@@ -43,12 +43,6 @@ public abstract class InputMethodManagerInternal {
        void onInputMethodListUpdated(List<InputMethodInfo> info, @UserIdInt int userId);
    }

    /**
     * Called by the power manager to tell the input method manager whether it
     * should start watching for wake events.
     */
    public abstract void setInteractive(boolean interactive);

    /**
     * Hides the current input method, if visible.
     */
@@ -102,10 +96,6 @@ public abstract class InputMethodManagerInternal {
     */
    private static final InputMethodManagerInternal NOP =
            new InputMethodManagerInternal() {
                @Override
                public void setInteractive(boolean interactive) {
                }

                @Override
                public void hideCurrentInputMethod(@SoftInputShowHideReason int reason) {
                }
+0 −24
Original line number Diff line number Diff line
@@ -4094,9 +4094,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                            + ((ClientState)msg.obj).uid);
                }
                return true;
            case MSG_SET_INTERACTIVE:
                handleSetInteractive(msg.arg1 != 0);
                return true;
            case MSG_REPORT_FULLSCREEN_MODE: {
                final boolean fullscreen = msg.arg1 != 0;
                final ClientState clientState = (ClientState)msg.obj;
@@ -4171,20 +4168,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
        return false;
    }

    private void handleSetInteractive(final boolean interactive) {
        synchronized (mMethodMap) {
            mIsInteractive = interactive;
            updateSystemUiLocked(interactive ? mImeWindowVis : 0, mBackDisposition);

            // Inform the current client of the change in active status
            if (mCurClient != null && mCurClient.client != null) {
                executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIIO(
                        MSG_SET_ACTIVE, mIsInteractive ? 1 : 0, mInFullscreenMode ? 1 : 0,
                        mCurClient));
            }
        }
    }

    private boolean chooseNewDefaultIMELocked() {
        final InputMethodInfo imi = InputMethodUtils.getMostApplicableDefaultIME(
                mSettings.getEnabledInputMethodListLocked());
@@ -4780,13 +4763,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
            mService = service;
        }

        @Override
        public void setInteractive(boolean interactive) {
            // Do everything in handler so as not to block the caller.
            mService.mHandler.obtainMessage(MSG_SET_INTERACTIVE, interactive ? 1 : 0, 0)
                    .sendToTarget();
        }

        @Override
        public void hideCurrentInputMethod(@SoftInputShowHideReason int reason) {
            mService.mHandler.removeMessages(MSG_HIDE_CURRENT_INPUT_METHOD);
+0 −5
Original line number Diff line number Diff line
@@ -169,11 +169,6 @@ public final class MultiClientInputMethodManagerService {

            LocalServices.addService(InputMethodManagerInternal.class,
                    new InputMethodManagerInternal() {
                        @Override
                        public void setInteractive(boolean interactive) {
                            reportNotSupported();
                        }

                        @Override
                        public void hideCurrentInputMethod(@SoftInputShowHideReason int reason) {
                            reportNotSupported();
Loading