summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;
}