Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d1e8129 authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

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
parent c1026e17
Loading
Loading
Loading
Loading
+58 −1
Original line number Diff line number Diff line
@@ -319,6 +319,25 @@ public final class InputMethodManager {
    int mCursorCandStart;
    int mCursorCandEnd;

    /**
     * Represents an invalid action notification sequence number. {@link InputMethodManagerService}
     * always issues a positive integer for action notification sequence numbers. Thus -1 is
     * guaranteed to be different from any valid sequence number.
     */
    private static final int NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER = -1;
    /**
     * The next sequence number that is to be sent to {@link InputMethodManagerService} via
     * {@link IInputMethodManager#notifyUserAction(int)} at once when a user action is observed.
     */
    private int mNextUserActionNotificationSequenceNumber =
            NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER;

    /**
     * The last sequence number that is already sent to {@link InputMethodManagerService}.
     */
    private int mLastSentUserActionNotificationSequenceNumber =
            NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER;

    /**
     * The instance that has previously been sent to the input method.
     */
@@ -364,6 +383,7 @@ public final class InputMethodManager {
    static final int MSG_TIMEOUT_INPUT_EVENT = 6;
    static final int MSG_FLUSH_INPUT_EVENT = 7;
    static final int MSG_SET_CURSOR_ANCHOR_MONITOR_MODE = 8;
    static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 9;

    class H extends Handler {
        H(Looper looper) {
@@ -503,6 +523,11 @@ public final class InputMethodManager {
                    }
                    return;
                }
                case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: {
                    synchronized (mH) {
                        mNextUserActionNotificationSequenceNumber = msg.arg1;
                    }
                }
            }
        }
    }
@@ -572,6 +597,12 @@ public final class InputMethodManager {
        public void setCursorAnchorMonitorMode(int monitorMode) {
            mH.sendMessage(mH.obtainMessage(MSG_SET_CURSOR_ANCHOR_MONITOR_MODE, monitorMode, 0));
        }

        @Override
        public void setUserActionNotificationSequenceNumber(int sequenceNumber) {
            mH.sendMessage(mH.obtainMessage(MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER,
                    sequenceNumber, 0));
        }
    };

    final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
@@ -1214,6 +1245,8 @@ public final class InputMethodManager {
                        mBindSequence = res.sequence;
                        mCurMethod = res.method;
                        mCurId = res.id;
                        mNextUserActionNotificationSequenceNumber =
                                res.userActionNotificationSequenceNumber;
                    } else {
                        if (res.channel != null && res.channel != mCurChannel) {
                            res.channel.dispose();
@@ -1918,8 +1951,28 @@ public final class InputMethodManager {
     */
    public void notifyUserAction() {
        synchronized (mH) {
            if (mLastSentUserActionNotificationSequenceNumber ==
                    mNextUserActionNotificationSequenceNumber) {
                if (DEBUG) {
                    Log.w(TAG, "Ignoring notifyUserAction as it has already been sent."
                            + " mLastSentUserActionNotificationSequenceNumber: "
                            + mLastSentUserActionNotificationSequenceNumber
                            + " mNextUserActionNotificationSequenceNumber: "
                            + mNextUserActionNotificationSequenceNumber);
                }
                return;
            }
            try {
                mService.notifyUserAction();
                if (DEBUG) {
                    Log.w(TAG, "notifyUserAction: "
                            + " mLastSentUserActionNotificationSequenceNumber: "
                            + mLastSentUserActionNotificationSequenceNumber
                            + " mNextUserActionNotificationSequenceNumber: "
                            + mNextUserActionNotificationSequenceNumber);
                }
                mService.notifyUserAction(mNextUserActionNotificationSequenceNumber);
                mLastSentUserActionNotificationSequenceNumber =
                        mNextUserActionNotificationSequenceNumber;
            } catch (RemoteException e) {
                Log.w(TAG, "IME died: " + mCurId, e);
            }
@@ -2103,6 +2156,10 @@ public final class InputMethodManager {
                + " mCursorSelEnd=" + mCursorSelEnd
                + " mCursorCandStart=" + mCursorCandStart
                + " mCursorCandEnd=" + mCursorCandEnd);
        p.println("  mNextUserActionNotificationSequenceNumber="
                + mNextUserActionNotificationSequenceNumber
                + " mLastSentUserActionNotificationSequenceNumber="
                + mLastSentUserActionNotificationSequenceNumber);
    }

    /**
+1 −0
Original line number Diff line number Diff line
@@ -28,4 +28,5 @@ oneway interface IInputMethodClient {
    void onUnbindMethod(int sequence);
    void setActive(boolean active);
    void setCursorAnchorMonitorMode(int monitorMode);
    void setUserActionNotificationSequenceNumber(int sequenceNumber);
}
+1 −1
Original line number Diff line number Diff line
@@ -77,6 +77,6 @@ interface IInputMethodManager {
    boolean setInputMethodEnabled(String id, boolean enabled);
    void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
    int getInputMethodWindowVisibleHeight();
    oneway void notifyUserAction();
    oneway void notifyUserAction(int sequenceNumber);
    void setCursorAnchorMonitorMode(in IBinder token, int monitorMode);
}
+13 −3
Original line number Diff line number Diff line
@@ -48,12 +48,18 @@ public final class InputBindResult implements Parcelable {
     */
    public final int sequence;

    /**
     * Sequence number of user action notification.
     */
    public final int userActionNotificationSequenceNumber;

    public InputBindResult(IInputMethodSession _method, InputChannel _channel,
            String _id, int _sequence) {
            String _id, int _sequence, int _userActionNotificationSequenceNumber) {
        method = _method;
        channel = _channel;
        id = _id;
        sequence = _sequence;
        userActionNotificationSequenceNumber = _userActionNotificationSequenceNumber;
    }
    
    InputBindResult(Parcel source) {
@@ -65,12 +71,15 @@ public final class InputBindResult implements Parcelable {
        }
        id = source.readString();
        sequence = source.readInt();
        userActionNotificationSequenceNumber = source.readInt();
    }

    @Override
    public String toString() {
        return "InputBindResult{" + method + " " + id
                + " #" + sequence + "}";
                + " sequence:" + sequence
                + " userActionNotificationSequenceNumber:" + userActionNotificationSequenceNumber
                + "}";
    }

    /**
@@ -90,6 +99,7 @@ public final class InputBindResult implements Parcelable {
        }
        dest.writeString(id);
        dest.writeInt(sequence);
        dest.writeInt(userActionNotificationSequenceNumber);
    }

    /**
+53 −8
Original line number Diff line number Diff line
@@ -149,6 +149,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
    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 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
    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 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
     */
    boolean mScreenOn = true;

    int mCurUserActionNotificationSequenceNumber = 0;

    int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
    int mImeWindowVis;

@@ -1129,7 +1132,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
            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 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                    // 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 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                    // 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 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
        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 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                        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 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
    }

    @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 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                            + " 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 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
        // 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 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                    + " mShowExplicitlyRequested=" + mShowExplicitlyRequested
                    + " mShowForced=" + mShowForced
                    + " mInputShown=" + mInputShown);
            p.println("  mCurUserActionNotificationSequenceNumber="
                    + mCurUserActionNotificationSequenceNumber);
            p.println("  mSystemReady=" + mSystemReady + " mInteractive=" + mScreenOn);
        }

Loading