diff options
| author | 2018-09-11 21:11:41 +0000 | |
|---|---|---|
| committer | 2018-09-11 21:11:41 +0000 | |
| commit | 48c882b4856df50697f6619b106f07d24ee93eca (patch) | |
| tree | d81f8475fbfa410114724c15f1ae2f7aa4b1f0b3 | |
| parent | 47c69efe8bf3fcf69ad19befcf09b4c8627a8c87 (diff) | |
| parent | c07fd4c2848302e30183d96475cc5c50c09a1c49 (diff) | |
Merge "Move notifyUserAction() to IInputMethodPrivilegedOperations"
11 files changed, 95 insertions, 147 deletions
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java index 185215a5ce75..b0fca006d1e2 100644 --- a/core/java/android/inputmethodservice/AbstractInputMethodService.java +++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java @@ -252,4 +252,12 @@ public abstract class AbstractInputMethodService extends Service return; } + /** + * Called when the user took some actions that should be taken into consideration to update the + * MRU list for input method rotation. + * + * @hide + */ + public void notifyUserActionIfNecessary() { + } } diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index aa5cf09f396b..2d12b867949a 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACK import static java.lang.annotation.RetentionPolicy.SOURCE; +import android.annotation.AnyThread; import android.annotation.CallSuper; import android.annotation.DrawableRes; import android.annotation.IntDef; @@ -79,6 +80,7 @@ import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; +import com.android.internal.annotations.GuardedBy; import com.android.internal.inputmethod.IInputContentUriToken; import com.android.internal.inputmethod.IInputMethodPrivilegedOperations; import com.android.internal.inputmethod.InputMethodPrivilegedOperations; @@ -402,6 +404,10 @@ public class InputMethodService extends AbstractInputMethodService { @BackDispositionMode int mBackDisposition; + private Object mLock = new Object(); + @GuardedBy("mLock") + private boolean mNotifyUserActionSent; + /** * {@code true} when the previous IME had non-empty inset at the bottom of the screen and we * have not shown our own window yet. In this situation, the previous inset continues to be @@ -594,7 +600,7 @@ public class InputMethodService extends AbstractInputMethodService { @MainThread @Override public void changeInputMethodSubtype(InputMethodSubtype subtype) { - onCurrentInputMethodSubtypeChanged(subtype); + dispatchOnCurrentInputMethodSubtypeChanged(subtype); } } @@ -2792,6 +2798,13 @@ public class InputMethodService extends AbstractInputMethodService { } } + private void dispatchOnCurrentInputMethodSubtypeChanged(InputMethodSubtype newSubtype) { + synchronized (mLock) { + mNotifyUserActionSent = false; + } + onCurrentInputMethodSubtypeChanged(newSubtype); + } + // TODO: Handle the subtype change event /** * Called when the subtype was changed. @@ -2848,6 +2861,22 @@ public class InputMethodService extends AbstractInputMethodService { } /** + * {@inheritDoc} + * @hide + */ + @AnyThread + @Override + public final void notifyUserActionIfNecessary() { + synchronized (mLock) { + if (mNotifyUserActionSent) { + return; + } + mPrivOps.notifyUserActionAsync(); + mNotifyUserActionSent = true; + } + } + + /** * Allow the receiver of {@link InputContentInfo} to obtain a temporary read-only access * permission to the content. * diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 84d1b70b8d99..c51c5e2173e2 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -354,28 +354,6 @@ public final class InputMethodManager { int mCursorCandEnd; /** - * Represents an invalid action notification sequence number. - * {@link com.android.server.InputMethodManagerService} always issues a positive integer for - * action notification sequence numbers. Thus {@code -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 com.android.server.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 com.android.server.InputMethodManagerService}. - */ - private int mLastSentUserActionNotificationSequenceNumber = - NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER; - - /** * The instance that has previously been sent to the input method. */ private CursorAnchorInfo mCursorAnchorInfo = null; @@ -421,7 +399,6 @@ public final class InputMethodManager { static final int MSG_SEND_INPUT_EVENT = 5; static final int MSG_TIMEOUT_INPUT_EVENT = 6; static final int MSG_FLUSH_INPUT_EVENT = 7; - static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 9; static final int MSG_REPORT_FULLSCREEN_MODE = 10; private static boolean isAutofillUIShowing(View servedView) { @@ -558,12 +535,6 @@ public final class InputMethodManager { finishedInputEvent(msg.arg1, false, false); return; } - case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: { - synchronized (mH) { - mNextUserActionNotificationSequenceNumber = msg.arg1; - } - return; - } case MSG_REPORT_FULLSCREEN_MODE: { final boolean fullscreen = msg.arg1 != 0; InputConnection ic = null; @@ -606,11 +577,6 @@ public final class InputMethodManager { } @Override - protected void onUserAction() { - mParentInputMethodManager.notifyUserAction(); - } - - @Override public String toString() { return "ControlledInputConnectionWrapper{" + "connection=" + getInputConnection() @@ -657,12 +623,6 @@ public final class InputMethodManager { } @Override - public void setUserActionNotificationSequenceNumber(int sequenceNumber) { - mH.obtainMessage(MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER, sequenceNumber, 0) - .sendToTarget(); - } - - @Override public void reportFullscreenMode(boolean fullscreen) { mH.obtainMessage(MSG_REPORT_FULLSCREEN_MODE, fullscreen ? 1 : 0, 0) .sendToTarget(); @@ -1355,8 +1315,6 @@ 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(); } @@ -2190,37 +2148,16 @@ public final class InputMethodManager { /** * Notify that a user took some action with this input method. + * + * @deprecated Just kept to avoid possible app compat issue. * @hide */ + @Deprecated @UnsupportedAppUsage(trackingBug = 114740982, maxTargetSdk = Build.VERSION_CODES.P) 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 { - if (DEBUG) { - Log.w(TAG, "notifyUserAction: " - + " mLastSentUserActionNotificationSequenceNumber: " - + mLastSentUserActionNotificationSequenceNumber - + " mNextUserActionNotificationSequenceNumber: " - + mNextUserActionNotificationSequenceNumber); - } - mService.notifyUserAction(mNextUserActionNotificationSequenceNumber); - mLastSentUserActionNotificationSequenceNumber = - mNextUserActionNotificationSequenceNumber; - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + Log.w(TAG, "notifyUserAction() is a hidden method, which is now just a stub method" + + " that does nothing. Leave comments in b.android.com/114740982 if your " + + " application still depends on the previous behavior of this method."); } /** @@ -2421,10 +2358,6 @@ public final class InputMethodManager { + " mCursorSelEnd=" + mCursorSelEnd + " mCursorCandStart=" + mCursorCandStart + " mCursorCandEnd=" + mCursorCandEnd); - p.println(" mNextUserActionNotificationSequenceNumber=" - + mNextUserActionNotificationSequenceNumber - + " mLastSentUserActionNotificationSequenceNumber=" - + mLastSentUserActionNotificationSequenceNumber); } /** diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl index e998a52665e2..c32894dd04f9 100644 --- a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl +++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl @@ -39,4 +39,6 @@ interface IInputMethodPrivilegedOperations { boolean switchToPreviousInputMethod(); boolean switchToNextInputMethod(boolean onlyCurrentIme); boolean shouldOfferSwitchingToNextInputMethod(); + + oneway void notifyUserActionAsync(); } diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java index 789154096d4c..f0e8dc59d09a 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java +++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java @@ -346,4 +346,20 @@ public final class InputMethodPrivilegedOperations { throw e.rethrowFromSystemServer(); } } + + /** + * Calls {@link IInputMethodPrivilegedOperations#notifyUserActionAsync()} + */ + @AnyThread + public void notifyUserActionAsync() { + final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull(); + if (ops == null) { + return; + } + try { + ops.notifyUserActionAsync(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java index d4c4ab343a14..6f9c87ab8f5a 100644 --- a/core/java/com/android/internal/view/IInputConnectionWrapper.java +++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java @@ -110,12 +110,6 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { abstract protected boolean isActive(); - /** - * Called when the user took some actions that should be taken into consideration to update the - * LRU list for input method rotation. - */ - abstract protected void onUserAction(); - public void getTextAfterCursor(int length, int flags, int seq, IInputContextCallback callback) { dispatchMessage(obtainMessageIISC(DO_GET_TEXT_AFTER_CURSOR, length, flags, seq, callback)); } @@ -342,7 +336,6 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { return; } ic.commitText((CharSequence)msg.obj, msg.arg1); - onUserAction(); return; } case DO_SET_SELECTION: { @@ -397,7 +390,6 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { return; } ic.setComposingText((CharSequence)msg.obj, msg.arg1); - onUserAction(); return; } case DO_SET_COMPOSING_REGION: { @@ -437,7 +429,6 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub { return; } ic.sendKeyEvent((KeyEvent)msg.obj); - onUserAction(); return; } case DO_CLEAR_META_KEY_STATES: { diff --git a/core/java/com/android/internal/view/IInputMethodClient.aidl b/core/java/com/android/internal/view/IInputMethodClient.aidl index 5c6dea88ac0e..2618356d7a09 100644 --- a/core/java/com/android/internal/view/IInputMethodClient.aidl +++ b/core/java/com/android/internal/view/IInputMethodClient.aidl @@ -27,6 +27,5 @@ oneway interface IInputMethodClient { // unbindReason corresponds to InputMethodClient.UnbindReason. void onUnbindMethod(int sequence, int unbindReason); void setActive(boolean active, boolean fullscreen); - void setUserActionNotificationSequenceNumber(int sequenceNumber); void reportFullscreenMode(boolean fullscreen); } diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 5afc53fe452d..543f4a532307 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -79,6 +79,4 @@ interface IInputMethodManager { // This is kept due to @UnsupportedAppUsage. // TODO(Bug 113914148): Consider removing this. int getInputMethodWindowVisibleHeight(); - - oneway void notifyUserAction(int sequenceNumber); } diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java index 9d4383f40266..e03c1f8621be 100644 --- a/core/java/com/android/internal/view/InputBindResult.java +++ b/core/java/com/android/internal/view/InputBindResult.java @@ -171,20 +171,13 @@ public final class InputBindResult implements Parcelable { */ public final int sequence; - /** - * Sequence number of user action notification. - */ - public final int userActionNotificationSequenceNumber; - public InputBindResult(@ResultCode int _result, - IInputMethodSession _method, InputChannel _channel, - String _id, int _sequence, int _userActionNotificationSequenceNumber) { + IInputMethodSession _method, InputChannel _channel, String _id, int _sequence) { result = _result; method = _method; channel = _channel; id = _id; sequence = _sequence; - userActionNotificationSequenceNumber = _userActionNotificationSequenceNumber; } InputBindResult(Parcel source) { @@ -197,14 +190,12 @@ public final class InputBindResult implements Parcelable { } id = source.readString(); sequence = source.readInt(); - userActionNotificationSequenceNumber = source.readInt(); } @Override public String toString() { return "InputBindResult{result=" + getResultString() + " method="+ method + " id=" + id + " sequence=" + sequence - + " userActionNotificationSequenceNumber=" + userActionNotificationSequenceNumber + "}"; } @@ -226,7 +217,6 @@ public final class InputBindResult implements Parcelable { } dest.writeString(id); dest.writeInt(sequence); - dest.writeInt(userActionNotificationSequenceNumber); } /** @@ -285,7 +275,7 @@ public final class InputBindResult implements Parcelable { } private static InputBindResult error(@ResultCode int result) { - return new InputBindResult(result, null, null, null, -1, -1); + return new InputBindResult(result, null, null, null, -1); } /** diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java index 5b65bbe1e90e..3bd3072c0ebe 100644 --- a/core/java/com/android/internal/view/InputConnectionWrapper.java +++ b/core/java/com/android/internal/view/InputConnectionWrapper.java @@ -371,6 +371,7 @@ public class InputConnectionWrapper implements InputConnection { public boolean commitText(CharSequence text, int newCursorPosition) { try { mIInputContext.commitText(text, newCursorPosition); + notifyUserActionIfNecessary(); return true; } catch (RemoteException e) { return false; @@ -378,6 +379,16 @@ public class InputConnectionWrapper implements InputConnection { } @AnyThread + private void notifyUserActionIfNecessary() { + final AbstractInputMethodService inputMethodService = mInputMethodService.get(); + if (inputMethodService == null) { + // This basically should not happen, because it's the the caller of this method. + return; + } + inputMethodService.notifyUserActionIfNecessary(); + } + + @AnyThread public boolean commitCompletion(CompletionInfo text) { if (isMethodMissing(MissingMethodFlags.COMMIT_CORRECTION)) { // This method is not implemented. @@ -449,6 +460,7 @@ public class InputConnectionWrapper implements InputConnection { public boolean setComposingText(CharSequence text, int newCursorPosition) { try { mIInputContext.setComposingText(text, newCursorPosition); + notifyUserActionIfNecessary(); return true; } catch (RemoteException e) { return false; @@ -489,6 +501,7 @@ public class InputConnectionWrapper implements InputConnection { public boolean sendKeyEvent(KeyEvent event) { try { mIInputContext.sendKeyEvent(event); + notifyUserActionIfNecessary(); return true; } catch (RemoteException e) { return false; diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 93d023da88d9..e435a4fd6384 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -210,7 +210,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub static final int MSG_BIND_CLIENT = 3010; static final int MSG_SET_ACTIVE = 3020; static final int MSG_SET_INTERACTIVE = 3030; - static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 3040; static final int MSG_REPORT_FULLSCREEN_MODE = 3045; static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000; @@ -598,8 +597,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub */ boolean mIsInteractive = true; - int mCurUserActionNotificationSequenceNumber = 0; - int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT; /** @@ -1822,7 +1819,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } return new InputBindResult(InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION, session.session, (session.channel != null ? session.channel.dup() : null), - mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber); + mCurId, mCurSeq); } @GuardedBy("mMethodMap") @@ -1881,8 +1878,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub requestClientSessionLocked(cs); return new InputBindResult( InputBindResult.ResultCode.SUCCESS_WAITING_IME_SESSION, - null, null, mCurId, mCurSeq, - mCurUserActionNotificationSequenceNumber); + null, null, mCurId, mCurSeq); } else if (SystemClock.uptimeMillis() < (mLastBindTime+TIME_TO_RECONNECT)) { // In this case we have connected to the service, but @@ -1894,8 +1890,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // to see if we can get back in touch with the service. return new InputBindResult( InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING, - null, null, mCurId, mCurSeq, - mCurUserActionNotificationSequenceNumber); + null, null, mCurId, mCurSeq); } else { EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0); @@ -1917,8 +1912,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // party code. return new InputBindResult( InputBindResult.ResultCode.ERROR_SYSTEM_NOT_READY, - null, null, mCurMethodId, mCurSeq, - mCurUserActionNotificationSequenceNumber); + null, null, mCurMethodId, mCurSeq); } InputMethodInfo info = mMethodMap.get(mCurMethodId); @@ -1946,8 +1940,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } return new InputBindResult( InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING, - null, null, mCurId, mCurSeq, - mCurUserActionNotificationSequenceNumber); + null, null, mCurId, mCurSeq); } mCurIntent = null; Slog.w(TAG, "Failure connecting to input method service: " + mCurIntent); @@ -2754,7 +2747,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } return new InputBindResult( InputBindResult.ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY, - null, null, null, -1, -1); + null, null, null, -1); } mCurFocusedWindow = windowToken; mCurFocusedWindowSoftInputMode = softInputMode; @@ -3172,17 +3165,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mWindowManagerInternal.clearLastInputMethodWindowForTransition(); } - @Override - public void notifyUserAction(int sequenceNumber) { + @BinderThread + private void notifyUserAction(@NonNull IBinder token) { if (DEBUG) { - Slog.d(TAG, "Got the notification of a user action. sequenceNumber:" + sequenceNumber); + Slog.d(TAG, "Got the notification of a user action."); } synchronized (mMethodMap) { - if (mCurUserActionNotificationSequenceNumber != sequenceNumber) { + if (mCurToken != token) { if (DEBUG) { - Slog.d(TAG, "Ignoring the user action notification due to the sequence number " - + "mismatch. expected:" + mCurUserActionNotificationSequenceNumber - + " actual: " + sequenceNumber); + Slog.d(TAG, "Ignoring the user action notification from IMEs that are no longer" + + " active."); } return; } @@ -3445,20 +3437,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub case MSG_START_VR_INPUT: startVrInputMethodNoCheck((ComponentName) msg.obj); return true; - case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: { - final int sequenceNumber = msg.arg1; - final ClientState clientState = (ClientState)msg.obj; - try { - clientState.client.setUserActionNotificationSequenceNumber(sequenceNumber); - } catch (RemoteException e) { - Slog.w(TAG, "Got RemoteException sending " - + "setUserActionNotificationSequenceNumber(" - + sequenceNumber + ") notification to pid " - + clientState.pid + " uid " - + clientState.uid); - } - return true; - } case MSG_REPORT_FULLSCREEN_MODE: { final boolean fullscreen = msg.arg1 != 0; final ClientState clientState = (ClientState)msg.obj; @@ -3944,19 +3922,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub 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)); - } - if (isVrInput) { // Updates to InputMethod are transient in VR mode. Any changes to Settings are skipped. return; @@ -4558,8 +4523,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub + " mShowForced=" + mShowForced + " mInputShown=" + mInputShown); p.println(" mInFullscreenMode=" + mInFullscreenMode); - p.println(" mCurUserActionNotificationSequenceNumber=" - + mCurUserActionNotificationSequenceNumber); p.println(" mSystemReady=" + mSystemReady + " mInteractive=" + mIsInteractive); p.println(" mSettingsObserver=" + mSettingsObserver); p.println(" mSwitchingController:"); @@ -5057,5 +5020,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub public boolean shouldOfferSwitchingToNextInputMethod() { return mImms.shouldOfferSwitchingToNextInputMethod(mToken); } + + @BinderThread + @Override + public void notifyUserActionAsync() { + mImms.notifyUserAction(mToken); + } } } |