diff options
author | Seigo Nonaka <nona@google.com> | 2015-05-26 20:54:43 +0900 |
---|---|---|
committer | Seigo Nonaka <nona@google.com> | 2015-06-02 10:32:48 +0900 |
commit | d9eb911bb99df4d092dea00e52bcb9a1feac39a7 (patch) | |
tree | 845b94e7991669aa5197da2d0aa384c4f1981a35 | |
parent | 29932d13a90e02c3fce680e68de975a5d77ab9db (diff) | |
download | frameworks_base-d9eb911bb99df4d092dea00e52bcb9a1feac39a7.zip frameworks_base-d9eb911bb99df4d092dea00e52bcb9a1feac39a7.tar.gz frameworks_base-d9eb911bb99df4d092dea00e52bcb9a1feac39a7.tar.bz2 |
Hide the software input based on its state.
This is a 2nd trial of I20ae2749a which is reverted due to a regression.
The goals of this CL are two:
- Split setImeWindowStatus method into two: keeping IMS status and
updating system UI e.g. NavBar icon state.
- Hide software keyboard based on a realistic IMS status.
IMMS#mImeWindowVis has been used for two purpose, keeping IMS status and
updating the NavBar icons, e.g. keyboard icon.
However, to update NavBar icon, sometimes IMMS#mImeWindowVis value is
updated without any notification from IMS. As the result, the status
value becomes incosistent with the real IMS state.
This patch extracts NavBar update logic into separate method and keeps
IMMS#mImeWindowVis as notified status. Then, use it for hiding software
input correctly in IMMS#hideCurrentInputLocked.
This CL also removes refreshImeWindowVisibilityLocked method including
workaround for fixing Bug 11186297. That issue is no longer
reproducible with latest lock screen and almost no effect for existing
users and developers. So simply remove them in this CL.
BUG: 21446788
BUG: 20764441
BUG: 18722991
Change-Id: I33dc6278fd892f26e56352722bf9449b8b102030
-rw-r--r-- | services/core/java/com/android/server/InputMethodManagerService.java | 184 |
1 files changed, 97 insertions, 87 deletions
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index ab0c8a9..201a4ca 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -398,6 +398,23 @@ public class InputMethodManagerService extends IInputMethodManager.Stub int mCurUserActionNotificationSequenceNumber = 0; int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT; + + /** + * A set of status bits regarding the active IME. + * + * <p>This value is a combination of following two bits:</p> + * <dl> + * <dt>{@link InputMethodService#IME_ACTIVE}</dt> + * <dd> + * If this bit is ON, connected IME is ready to accept touch/key events. + * </dd> + * <dt>{@link InputMethodService#IME_VISIBLE}</dt> + * <dd> + * If this bit is ON, some of IME view, e.g. software input, candidate view, is visible. + * </dd> + * </dl> + * <em>Do not update this value outside of setImeWindowStatus.</em> + */ int mImeWindowVis; private AlertDialog.Builder mDialogBuilder; @@ -459,12 +476,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final String action = intent.getAction(); if (Intent.ACTION_SCREEN_ON.equals(action)) { mScreenOn = true; - refreshImeWindowVisibilityLocked(); + updateSystemUi(mCurToken, mImeWindowVis, mBackDisposition); updateActive(); return; } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { mScreenOn = false; - setImeWindowVisibilityStatusHiddenLocked(); + updateSystemUi(mCurToken, 0 /* vis */, mBackDisposition); updateActive(); return; } else if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) { @@ -660,7 +677,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Uh oh, current input method is no longer around! // Pick another one... Slog.i(TAG, "Current input method removed: " + curInputMethodId); - setImeWindowVisibilityStatusHiddenLocked(); + updateSystemUiLocked(mCurToken, 0 /* vis */, mBackDisposition); if (!chooseNewDefaultIMELocked()) { changed = true; curIm = null; @@ -1003,7 +1020,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mContext.getSystemService(Context.NOTIFICATION_SERVICE); mStatusBar = statusBar; statusBar.setIconVisibility("ime", false); - updateImeWindowStatusLocked(); + updateSystemUiLocked(mCurToken, mImeWindowVis, mBackDisposition); mShowOngoingImeSwitcherForPhones = mRes.getBoolean( com.android.internal.R.bool.show_ongoing_ime_switcher); if (mShowOngoingImeSwitcherForPhones) { @@ -1029,33 +1046,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - private void setImeWindowVisibilityStatusHiddenLocked() { - mImeWindowVis = 0; - updateImeWindowStatusLocked(); - } - - private void refreshImeWindowVisibilityLocked() { - final Configuration conf = mRes.getConfiguration(); - final boolean haveHardKeyboard = conf.keyboard - != Configuration.KEYBOARD_NOKEYS; - final boolean hardKeyShown = haveHardKeyboard - && conf.hardKeyboardHidden - != Configuration.HARDKEYBOARDHIDDEN_YES; - - final boolean isScreenLocked = isKeyguardLocked(); - final boolean inputActive = !isScreenLocked && (mInputShown || hardKeyShown); - // We assume the softkeyboard is shown when the input is active as long as the - // hard keyboard is not shown. - final boolean inputVisible = inputActive && !hardKeyShown; - mImeWindowVis = (inputActive ? InputMethodService.IME_ACTIVE : 0) - | (inputVisible ? InputMethodService.IME_VISIBLE : 0); - updateImeWindowStatusLocked(); - } - - private void updateImeWindowStatusLocked() { - setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition); - } - // --------------------------------------------------------------------------------------- // Check whether or not this is a valid IPC. Assumes an IPC is valid when either // 1) it comes from the system process @@ -1541,7 +1531,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub sessionState.session.finishSession(); } catch (RemoteException e) { Slog.w(TAG, "Session failed to close due to remote exception", e); - setImeWindowVisibilityStatusHiddenLocked(); + updateSystemUiLocked(mCurToken, 0 /* vis */, mBackDisposition); } sessionState.session = null; } @@ -1629,11 +1619,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - private boolean shouldShowImeSwitcherLocked() { + private boolean shouldShowImeSwitcherLocked(int visibility) { if (!mShowOngoingImeSwitcherForPhones) return false; if (mSwitchingDialog != null) return false; if (isScreenLocked()) return false; - if ((mImeWindowVis & InputMethodService.IME_ACTIVE) == 0) return false; + if ((visibility & InputMethodService.IME_ACTIVE) == 0) return false; if (mWindowManagerService.isHardKeyboardAvailable()) { // When physical keyboard is attached, we show the ime switcher (or notification if // NavBar is not available) because SHOW_IME_WITH_HARD_KEYBOARD settings currently @@ -1641,7 +1631,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // SHOW_IME_WITH_HARD_KEYBOARD settings finds a good place to live. return true; } - if ((mImeWindowVis & InputMethodService.IME_VISIBLE) == 0) return false; + if ((visibility & InputMethodService.IME_VISIBLE) == 0) return false; List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked(); final int N = imis.size(); @@ -1690,62 +1680,82 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked(); } - // Caution! This method is called in this class. Handle multi-user carefully @SuppressWarnings("deprecation") @Override public void setImeWindowStatus(IBinder token, int vis, int backDisposition) { + if (!calledWithValidToken(token)) { + final int uid = Binder.getCallingUid(); + Slog.e(TAG, "Ignoring setImeWindowStatus due to an invalid token. uid:" + uid + + " token:" + token); + return; + } + + synchronized (mMethodMap) { + mImeWindowVis = vis; + mBackDisposition = backDisposition; + updateSystemUiLocked(token, vis, backDisposition); + } + } + + private void updateSystemUi(IBinder token, int vis, int backDisposition) { + synchronized (mMethodMap) { + updateSystemUiLocked(token, vis, backDisposition); + } + } + + // Caution! This method is called in this class. Handle multi-user carefully + private void updateSystemUiLocked(IBinder token, int vis, int backDisposition) { + if (!calledWithValidToken(token)) { + final int uid = Binder.getCallingUid(); + Slog.e(TAG, "Ignoring updateSystemUiLocked due to an invalid token. uid:" + uid + + " token:" + token); + return; + } + + // TODO: Move this clearing calling identity block to setImeWindowStatus after making sure + // all updateSystemUi happens on system previlege. final long ident = Binder.clearCallingIdentity(); try { - if (!calledWithValidToken(token)) { - final int uid = Binder.getCallingUid(); - Slog.e(TAG, "Ignoring setImeWindowStatus due to an invalid token. uid:" + uid - + " token:" + token); - return; + // apply policy for binder calls + if (vis != 0 && isKeyguardLocked() && !mCurClientInKeyguard) { + vis = 0; } - synchronized (mMethodMap) { - // apply policy for binder calls - if (vis != 0 && isKeyguardLocked() && !mCurClientInKeyguard) { - vis = 0; - } - mImeWindowVis = vis; - mBackDisposition = backDisposition; - // mImeWindowVis should be updated before calling shouldShowImeSwitcherLocked(). - final boolean needsToShowImeSwitcher = shouldShowImeSwitcherLocked(); - if (mStatusBar != null) { - mStatusBar.setImeWindowStatus(token, vis, backDisposition, - needsToShowImeSwitcher); - } - final InputMethodInfo imi = mMethodMap.get(mCurMethodId); - if (imi != null && needsToShowImeSwitcher) { - // Used to load label - final CharSequence title = mRes.getText( - com.android.internal.R.string.select_input_method); - final CharSequence summary = InputMethodUtils.getImeAndSubtypeDisplayName( - mContext, imi, mCurrentSubtype); - - mImeSwitcherNotification.color = mContext.getColor( - com.android.internal.R.color.system_notification_accent_color); - mImeSwitcherNotification.setLatestEventInfo( - mContext, title, summary, mImeSwitchPendingIntent); - if ((mNotificationManager != null) - && !mWindowManagerService.hasNavigationBar()) { - if (DEBUG) { - Slog.d(TAG, "--- show notification: label = " + summary); - } - mNotificationManager.notifyAsUser(null, - com.android.internal.R.string.select_input_method, - mImeSwitcherNotification, UserHandle.ALL); - mNotificationShown = true; + // mImeWindowVis should be updated before calling shouldShowImeSwitcherLocked(). + final boolean needsToShowImeSwitcher = shouldShowImeSwitcherLocked(vis); + if (mStatusBar != null) { + mStatusBar.setImeWindowStatus(token, vis, backDisposition, + needsToShowImeSwitcher); + } + final InputMethodInfo imi = mMethodMap.get(mCurMethodId); + if (imi != null && needsToShowImeSwitcher) { + // Used to load label + final CharSequence title = mRes.getText( + com.android.internal.R.string.select_input_method); + final CharSequence summary = InputMethodUtils.getImeAndSubtypeDisplayName( + mContext, imi, mCurrentSubtype); + + mImeSwitcherNotification.color = mContext.getColor( + com.android.internal.R.color.system_notification_accent_color); + mImeSwitcherNotification.setLatestEventInfo( + mContext, title, summary, mImeSwitchPendingIntent); + if ((mNotificationManager != null) + && !mWindowManagerService.hasNavigationBar()) { + if (DEBUG) { + Slog.d(TAG, "--- show notification: label = " + summary); } - } else { - if (mNotificationShown && mNotificationManager != null) { - if (DEBUG) { - Slog.d(TAG, "--- hide notification"); - } - mNotificationManager.cancelAsUser(null, - com.android.internal.R.string.select_input_method, UserHandle.ALL); - mNotificationShown = false; + mNotificationManager.notifyAsUser(null, + com.android.internal.R.string.select_input_method, + mImeSwitcherNotification, UserHandle.ALL); + mNotificationShown = true; + } + } else { + if (mNotificationShown && mNotificationManager != null) { + if (DEBUG) { + Slog.d(TAG, "--- hide notification"); } + mNotificationManager.cancelAsUser(null, + com.android.internal.R.string.select_input_method, UserHandle.ALL); + mNotificationShown = false; } } } finally { @@ -1912,7 +1922,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true); if (mCurMethod != null) { try { - refreshImeWindowVisibilityLocked(); + updateSystemUiLocked(mCurToken, mImeWindowVis, mBackDisposition); mCurMethod.changeInputMethodSubtype(newSubtype); } catch (RemoteException e) { Slog.w(TAG, "Failed to call changeInputMethodSubtype"); @@ -2074,7 +2084,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub return false; } boolean res; - if (mInputShown && mCurMethod != null) { + if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && mCurMethod != null) { executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO( MSG_HIDE_SOFT_INPUT, mCurMethod, resultReceiver)); res = true; @@ -3048,7 +3058,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mSwitchingDialog.getWindow().getAttributes().privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; mSwitchingDialog.getWindow().getAttributes().setTitle("Select input method"); - updateImeWindowStatusLocked(); + updateSystemUi(mCurToken, mImeWindowVis, mBackDisposition); mSwitchingDialog.show(); } } @@ -3107,7 +3117,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mSwitchingDialog = null; } - updateImeWindowStatusLocked(); + updateSystemUiLocked(mCurToken, mImeWindowVis, mBackDisposition); mDialogBuilder = null; mIms = null; } |