From 0df8812486ff0b104622dec72d6243a783b10257 Mon Sep 17 00:00:00 2001 From: lumark Date: Wed, 27 Nov 2019 22:13:41 +0800 Subject: [PATCH] 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 31e4e149941e34cd135dfa0b6d918cc0b3dabbbc [2]. Fix a crash in InputMethodManager when switching the IME in the system process (Bug 6789252) I66f51da1299532793ef8fa700f35b0811670f235 4e5184f929d2498714bc7734fe10b9b8810cb071 [3]. Call startInput on return from sleep mode (Bug 17558972) I95d05110bc1cf310fad23ea1bcbc5890f642d1fc 82ae3ff4cf268f577e19c410b120314cdc11a191 [4]. Make IMM more robust to spurious window focus-in (Bug 26851566) I60adb38013b063918b074c7b947649eada77b2c8 8e9214b4bd7e6a9d944ad1527199226e575a7530 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 --- .../java/android/view/ImeFocusController.java | 20 ++++++++++++++++ core/java/android/view/ViewRootImpl.java | 1 + .../InputMethodManagerInternal.java | 10 -------- .../InputMethodManagerService.java | 24 ------------------- .../MultiClientInputMethodManagerService.java | 5 ---- .../com/android/server/power/Notifier.java | 1 - 6 files changed, 21 insertions(+), 40 deletions(-) diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java index 67e88a5a1831f..74fac2b404723 100644 --- a/core/java/android/view/ImeFocusController.java +++ b/core/java/android/view/ImeFocusController.java @@ -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. diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 4a093e6038b8c..b4b27411521e3 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -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. diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java index f24699a6ae647..68e6c1885ec2c 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java @@ -43,12 +43,6 @@ public abstract class InputMethodManagerInternal { void onInputMethodListUpdated(List 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) { } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index e3c545c3cf28a..13595b7f8b1cc 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -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); diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java index 1aff23b09c0fd..039a151fca194 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -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(); diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index 0b95be15f1575..199cb4981fe67 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -413,7 +413,6 @@ public class Notifier { // Start input as soon as we start waking up or going to sleep. mInputManagerInternal.setInteractive(interactive); - mInputMethodManagerInternal.setInteractive(interactive); // Notify battery stats. try {