summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeigo Nonaka <nona@google.com>2015-05-26 20:54:43 +0900
committerSeigo Nonaka <nona@google.com>2015-06-02 10:32:48 +0900
commitd9eb911bb99df4d092dea00e52bcb9a1feac39a7 (patch)
tree845b94e7991669aa5197da2d0aa384c4f1981a35
parent29932d13a90e02c3fce680e68de975a5d77ab9db (diff)
downloadframeworks_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.java184
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;
}