From 2c6e80be1253140f1761c1bb4cc601e7e350e1b2 Mon Sep 17 00:00:00 2001 From: Ming-Shin Lu Date: Wed, 13 May 2020 00:12:26 +0800 Subject: [PATCH] Revert "Finish input when the screen state is off" This reverts commit 0df8812486ff0b104622dec72d6243a783b10257. The original CL is trying to reduce the dependency of PownerManager to finish input when screen off by using display state. However, it doesn't fully fix the original Bug 26851566 since we only finish input connection but didn't callback onFinishInput callback for IME client. Also, for some scenarios, the window / view focus may not change during screen turns off / on: - Focusing timing when disable keyguard, then quickly screen off / on. - Using P-sensor to turning screen off / on. When the above scenario happens, makes input connection cannot re-start and soft-keyboard can't be shown. (The recovery is manually focus on next window or activity.) As the above reason, we need to re-consider the lifecycle of input connection, window / view focus when not only screen state but also device inactive state when always-on-display. Fix: 156045961 Fix: 154605805 Bug: 26851566 Bug: 156215187 Test: atest CtsInputMethodTestCases Change-Id: If06daf71160aa44a4254ac125561974ecbdef4f2 --- .../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, 40 insertions(+), 21 deletions(-) diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java index dbbe4b61c81c9..a4800726bbe8b 100644 --- a/core/java/android/view/ImeFocusController.java +++ b/core/java/android/view/ImeFocusController.java @@ -207,26 +207,6 @@ 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 5b9cd7786a39e..d36a2381f159b 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1496,7 +1496,6 @@ 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 d49d4b2c3278e..de13bd86a4155 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java @@ -44,6 +44,12 @@ 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. */ @@ -107,6 +113,10 @@ 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 b949d6bcf2e25..6efc88e017af1 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -4202,6 +4202,9 @@ 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; @@ -4276,6 +4279,20 @@ 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()); @@ -4884,6 +4901,13 @@ 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 0b73e4f0e9b4e..2129e9bd34f3f 100644 --- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java @@ -170,6 +170,11 @@ 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 199cb4981fe67..0b95be15f1575 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -413,6 +413,7 @@ 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 {