Introduce a sequence number to avoid redundant IPCs
This CL introduces a sequence number to avoid redundant IPCs
between IMM and IMMS. The basic concept is that:
1. IMMS maintains a sequence number for #notifyUserAction.
2. IMMS increases the sequence number whenever the current
IME/subtype is changed.
3. IMMS notifies the new sequence number to IMM.
4. IMM maintains the last sent sequence number and the next
sequence number. IMM should call #notifyUserAction only
once per particular sequence number.
5. IMMS ignores #notifyUserAction if the specified sequence
number is not the expected one.
BUG: 7043015
Change-Id: I19ad8542659bc092b92ee13eb9f1d68ddd4b815a
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 251247c..8fb2e9f 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -149,6 +149,7 @@
static final int MSG_BIND_METHOD = 3010;
static final int MSG_SET_ACTIVE = 3020;
static final int MSG_SET_CURSOR_ANCHOR_MONITOR_MODE = 3030;
+ static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 3040;
static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
@@ -172,7 +173,7 @@
private final HardKeyboardListener mHardKeyboardListener;
private final WindowManagerService mWindowManagerService;
- final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1);
+ final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1, -1);
// All known input methods. mMethodMap also serves as the global
// lock for this class.
@@ -379,6 +380,8 @@
*/
boolean mScreenOn = true;
+ int mCurUserActionNotificationSequenceNumber = 0;
+
int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
int mImeWindowVis;
@@ -1129,7 +1132,8 @@
showCurrentInputLocked(getAppShowFlags(), null);
}
return new InputBindResult(session.session,
- session.channel != null ? session.channel.dup() : null, mCurId, mCurSeq);
+ (session.channel != null ? session.channel.dup() : null),
+ mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
}
InputBindResult startInputLocked(IInputMethodClient client,
@@ -1205,7 +1209,8 @@
// Return to client, and we will get back with it when
// we have had a session made for it.
requestClientSessionLocked(cs);
- return new InputBindResult(null, null, mCurId, mCurSeq);
+ return new InputBindResult(null, null, mCurId, mCurSeq,
+ mCurUserActionNotificationSequenceNumber);
} else if (SystemClock.uptimeMillis()
< (mLastBindTime+TIME_TO_RECONNECT)) {
// In this case we have connected to the service, but
@@ -1215,7 +1220,8 @@
// we can report back. If it has been too long, we want
// to fall through so we can try a disconnect/reconnect
// to see if we can get back in touch with the service.
- return new InputBindResult(null, null, mCurId, mCurSeq);
+ return new InputBindResult(null, null, mCurId, mCurSeq,
+ mCurUserActionNotificationSequenceNumber);
} else {
EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);
@@ -1234,7 +1240,8 @@
if (!mSystemReady) {
// If the system is not yet ready, we shouldn't be running third
// party code.
- return new InputBindResult(null, null, mCurMethodId, mCurSeq);
+ return new InputBindResult(null, null, mCurMethodId, mCurSeq,
+ mCurUserActionNotificationSequenceNumber);
}
InputMethodInfo info = mMethodMap.get(mCurMethodId);
@@ -1263,7 +1270,8 @@
WindowManager.LayoutParams.TYPE_INPUT_METHOD);
} catch (RemoteException e) {
}
- return new InputBindResult(null, null, mCurId, mCurSeq);
+ return new InputBindResult(null, null, mCurId, mCurSeq,
+ mCurUserActionNotificationSequenceNumber);
} else {
mCurIntent = null;
Slog.w(TAG, "Failure connecting to input method service: "
@@ -2310,11 +2318,19 @@
}
@Override
- public void notifyUserAction() {
+ public void notifyUserAction(int sequenceNumber) {
if (DEBUG) {
- Slog.d(TAG, "Got the notification of a user action");
+ Slog.d(TAG, "Got the notification of a user action. sequenceNumber:" + sequenceNumber);
}
synchronized (mMethodMap) {
+ if (mCurUserActionNotificationSequenceNumber != sequenceNumber) {
+ if (DEBUG) {
+ Slog.d(TAG, "Ignoring the user action notification due to the sequence number "
+ + "mismatch. expected:" + mCurUserActionNotificationSequenceNumber
+ + " actual: " + sequenceNumber);
+ }
+ return;
+ }
final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
if (imi != null) {
mSwitchingController.onUserActionLocked(imi, mCurrentSubtype);
@@ -2588,6 +2604,20 @@
+ " uid " + ((ClientState)msg.obj).uid);
}
return true;
+ case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: {
+ final int sequenceNumber = msg.arg1;
+ final IInputMethodClient client = (IInputMethodClient)msg.obj;
+ try {
+ client.setUserActionNotificationSequenceNumber(sequenceNumber);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Got RemoteException sending "
+ + "setUserActionNotificationSequenceNumber("
+ + sequenceNumber + ") notification to pid "
+ + ((ClientState)msg.obj).pid + " uid "
+ + ((ClientState)msg.obj).uid);
+ }
+ return true;
+ }
// --------------------------------------------------------------
case MSG_HARD_KEYBOARD_SWITCH_CHANGED:
@@ -2999,6 +3029,19 @@
// Update the history of InputMethod and Subtype
mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype);
+ mCurUserActionNotificationSequenceNumber =
+ Math.max(mCurUserActionNotificationSequenceNumber + 1, 1);
+ if (DEBUG) {
+ Slog.d(TAG, "Bump mCurUserActionNotificationSequenceNumber:"
+ + mCurUserActionNotificationSequenceNumber);
+ }
+
+ if (mCurClient != null && mCurClient.client != null) {
+ executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
+ MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER,
+ mCurUserActionNotificationSequenceNumber, mCurClient.client));
+ }
+
// Set Subtype here
if (imi == null || subtypeId < 0) {
mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
@@ -3490,6 +3533,8 @@
+ " mShowExplicitlyRequested=" + mShowExplicitlyRequested
+ " mShowForced=" + mShowForced
+ " mInputShown=" + mInputShown);
+ p.println(" mCurUserActionNotificationSequenceNumber="
+ + mCurUserActionNotificationSequenceNumber);
p.println(" mSystemReady=" + mSystemReady + " mInteractive=" + mScreenOn);
}