diff options
author | Jeff Brown <jeffbrown@google.com> | 2013-03-26 19:46:20 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2013-03-26 19:46:20 -0700 |
commit | 901b77c63bc707c5785a149975e2113a43e38ad6 (patch) | |
tree | 2766b887f99e37bcdc423ecf668b7ad6ee58d609 /core/java/android/inputmethodservice | |
parent | 483ac9a779af452d7ef4007d0e24c569ee894557 (diff) | |
parent | ca3d655d20c13c71972a4475cec3b98efa7dbdd0 (diff) |
am ca3d655d: Merge "Use input transport for communications between app and IME." into jb-mr2-dev
* commit 'ca3d655d20c13c71972a4475cec3b98efa7dbdd0':
Use input transport for communications between app and IME.
Diffstat (limited to 'core/java/android/inputmethodservice')
3 files changed, 138 insertions, 89 deletions
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java index 3c3182accc8e..3531926d347c 100644 --- a/core/java/android/inputmethodservice/AbstractInputMethodService.java +++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java @@ -126,11 +126,12 @@ public abstract class AbstractInputMethodService extends Service mRevoked = true; mEnabled = false; } - + /** * Take care of dispatching incoming key events to the appropriate * callbacks on the service, and tell the client when this is done. */ + @Override public void dispatchKeyEvent(int seq, KeyEvent event, EventCallback callback) { boolean handled = event.dispatch(AbstractInputMethodService.this, mDispatcherState, this); @@ -143,6 +144,7 @@ public abstract class AbstractInputMethodService extends Service * Take care of dispatching incoming trackball events to the appropriate * callbacks on the service, and tell the client when this is done. */ + @Override public void dispatchTrackballEvent(int seq, MotionEvent event, EventCallback callback) { boolean handled = onTrackballEvent(event); if (callback != null) { @@ -154,6 +156,7 @@ public abstract class AbstractInputMethodService extends Service * Take care of dispatching incoming generic motion events to the appropriate * callbacks on the service, and tell the client when this is done. */ + @Override public void dispatchGenericMotionEvent(int seq, MotionEvent event, EventCallback callback) { boolean handled = onGenericMotionEvent(event); if (callback != null) { diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java index d78262b6aacd..726dcec92eb5 100644 --- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java @@ -18,15 +18,20 @@ package android.inputmethodservice; import com.android.internal.os.HandlerCaller; import com.android.internal.os.SomeArgs; -import com.android.internal.view.IInputMethodCallback; import com.android.internal.view.IInputMethodSession; import android.content.Context; import android.graphics.Rect; import android.os.Bundle; +import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.util.Log; +import android.util.SparseArray; +import android.view.InputChannel; +import android.view.InputDevice; +import android.view.InputEvent; +import android.view.InputEventReceiver; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.inputmethod.CompletionInfo; @@ -36,14 +41,10 @@ import android.view.inputmethod.InputMethodSession; class IInputMethodSessionWrapper extends IInputMethodSession.Stub implements HandlerCaller.Callback { private static final String TAG = "InputMethodWrapper"; - private static final boolean DEBUG = false; private static final int DO_FINISH_INPUT = 60; private static final int DO_DISPLAY_COMPLETIONS = 65; private static final int DO_UPDATE_EXTRACTED_TEXT = 67; - private static final int DO_DISPATCH_KEY_EVENT = 70; - private static final int DO_DISPATCH_TRACKBALL_EVENT = 80; - private static final int DO_DISPATCH_GENERIC_MOTION_EVENT = 85; private static final int DO_UPDATE_SELECTION = 90; private static final int DO_UPDATE_CURSOR = 95; private static final int DO_APP_PRIVATE_COMMAND = 100; @@ -53,34 +54,30 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub HandlerCaller mCaller; InputMethodSession mInputMethodSession; - - // NOTE: we should have a cache of these. - static class InputMethodEventCallbackWrapper implements InputMethodSession.EventCallback { - final IInputMethodCallback mCb; - InputMethodEventCallbackWrapper(IInputMethodCallback cb) { - mCb = cb; - } - public void finishedEvent(int seq, boolean handled) { - try { - mCb.finishedEvent(seq, handled); - } catch (RemoteException e) { - } - } - } - + InputChannel mChannel; + ImeInputEventReceiver mReceiver; + public IInputMethodSessionWrapper(Context context, - InputMethodSession inputMethodSession) { + InputMethodSession inputMethodSession, InputChannel channel) { mCaller = new HandlerCaller(context, null, this, true /*asyncHandler*/); mInputMethodSession = inputMethodSession; + mChannel = channel; + if (channel != null) { + mReceiver = new ImeInputEventReceiver(channel, context.getMainLooper()); + } } public InputMethodSession getInternalInputMethodSession() { return mInputMethodSession; } + @Override public void executeMessage(Message msg) { - if (mInputMethodSession == null) return; + if (mInputMethodSession == null) { + // The session has been finished. + return; + } switch (msg.what) { case DO_FINISH_INPUT: @@ -93,33 +90,6 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub mInputMethodSession.updateExtractedText(msg.arg1, (ExtractedText)msg.obj); return; - case DO_DISPATCH_KEY_EVENT: { - SomeArgs args = (SomeArgs)msg.obj; - mInputMethodSession.dispatchKeyEvent(msg.arg1, - (KeyEvent)args.arg1, - new InputMethodEventCallbackWrapper( - (IInputMethodCallback)args.arg2)); - args.recycle(); - return; - } - case DO_DISPATCH_TRACKBALL_EVENT: { - SomeArgs args = (SomeArgs)msg.obj; - mInputMethodSession.dispatchTrackballEvent(msg.arg1, - (MotionEvent)args.arg1, - new InputMethodEventCallbackWrapper( - (IInputMethodCallback)args.arg2)); - args.recycle(); - return; - } - case DO_DISPATCH_GENERIC_MOTION_EVENT: { - SomeArgs args = (SomeArgs)msg.obj; - mInputMethodSession.dispatchGenericMotionEvent(msg.arg1, - (MotionEvent)args.arg1, - new InputMethodEventCallbackWrapper( - (IInputMethodCallback)args.arg2)); - args.recycle(); - return; - } case DO_UPDATE_SELECTION: { SomeArgs args = (SomeArgs)msg.obj; mInputMethodSession.updateSelection(args.argi1, args.argi2, @@ -143,7 +113,7 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub return; } case DO_FINISH_SESSION: { - mInputMethodSession = null; + doFinishSession(); return; } case DO_VIEW_CLICKED: { @@ -153,37 +123,37 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub } Log.w(TAG, "Unhandled message code: " + msg.what); } - + + private void doFinishSession() { + mInputMethodSession = null; + if (mReceiver != null) { + mReceiver.dispose(); + mReceiver = null; + } + if (mChannel != null) { + mChannel.dispose(); + mChannel = null; + } + } + + @Override public void finishInput() { mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_INPUT)); } + @Override public void displayCompletions(CompletionInfo[] completions) { mCaller.executeOrSendMessage(mCaller.obtainMessageO( DO_DISPLAY_COMPLETIONS, completions)); } - + + @Override public void updateExtractedText(int token, ExtractedText text) { mCaller.executeOrSendMessage(mCaller.obtainMessageIO( DO_UPDATE_EXTRACTED_TEXT, token, text)); } - - public void dispatchKeyEvent(int seq, KeyEvent event, IInputMethodCallback callback) { - mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_DISPATCH_KEY_EVENT, seq, - event, callback)); - } - - public void dispatchTrackballEvent(int seq, MotionEvent event, IInputMethodCallback callback) { - mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_DISPATCH_TRACKBALL_EVENT, seq, - event, callback)); - } - - public void dispatchGenericMotionEvent(int seq, MotionEvent event, - IInputMethodCallback callback) { - mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_DISPATCH_GENERIC_MOTION_EVENT, seq, - event, callback)); - } + @Override public void updateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) { mCaller.executeOrSendMessage(mCaller.obtainMessageIIIIII(DO_UPDATE_SELECTION, @@ -191,24 +161,74 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub candidatesStart, candidatesEnd)); } + @Override public void viewClicked(boolean focusChanged) { - mCaller.executeOrSendMessage(mCaller.obtainMessageI(DO_VIEW_CLICKED, focusChanged ? 1 : 0)); + mCaller.executeOrSendMessage( + mCaller.obtainMessageI(DO_VIEW_CLICKED, focusChanged ? 1 : 0)); } + @Override public void updateCursor(Rect newCursor) { - mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_UPDATE_CURSOR, - newCursor)); + mCaller.executeOrSendMessage( + mCaller.obtainMessageO(DO_UPDATE_CURSOR, newCursor)); } - + + @Override public void appPrivateCommand(String action, Bundle data) { - mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_APP_PRIVATE_COMMAND, action, data)); + mCaller.executeOrSendMessage( + mCaller.obtainMessageOO(DO_APP_PRIVATE_COMMAND, action, data)); } - + + @Override public void toggleSoftInput(int showFlags, int hideFlags) { - mCaller.executeOrSendMessage(mCaller.obtainMessageII(DO_TOGGLE_SOFT_INPUT, showFlags, hideFlags)); + mCaller.executeOrSendMessage( + mCaller.obtainMessageII(DO_TOGGLE_SOFT_INPUT, showFlags, hideFlags)); } + @Override public void finishSession() { mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_FINISH_SESSION)); } + + private final class ImeInputEventReceiver extends InputEventReceiver + implements InputMethodSession.EventCallback { + private final SparseArray<InputEvent> mPendingEvents = new SparseArray<InputEvent>(); + + public ImeInputEventReceiver(InputChannel inputChannel, Looper looper) { + super(inputChannel, looper); + } + + @Override + public void onInputEvent(InputEvent event) { + if (mInputMethodSession == null) { + // The session has been finished. + finishInputEvent(event, false); + return; + } + + final int seq = event.getSequenceNumber(); + mPendingEvents.put(seq, event); + if (event instanceof KeyEvent) { + KeyEvent keyEvent = (KeyEvent)event; + mInputMethodSession.dispatchKeyEvent(seq, keyEvent, this); + } else { + MotionEvent motionEvent = (MotionEvent)event; + if (motionEvent.isFromSource(InputDevice.SOURCE_CLASS_TRACKBALL)) { + mInputMethodSession.dispatchTrackballEvent(seq, motionEvent, this); + } else { + mInputMethodSession.dispatchGenericMotionEvent(seq, motionEvent, this); + } + } + } + + @Override + public void finishedEvent(int seq, boolean handled) { + int index = mPendingEvents.indexOfKey(seq); + if (index >= 0) { + InputEvent event = mPendingEvents.valueAt(index); + mPendingEvents.removeAt(index); + finishInputEvent(event, handled); + } + } + } } diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java index 0d981be7eb8f..93063739cfd6 100644 --- a/core/java/android/inputmethodservice/IInputMethodWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java @@ -32,6 +32,7 @@ import android.os.Message; import android.os.RemoteException; import android.os.ResultReceiver; import android.util.Log; +import android.view.InputChannel; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputBinding; import android.view.inputmethod.InputConnection; @@ -53,7 +54,6 @@ import java.util.concurrent.TimeUnit; class IInputMethodWrapper extends IInputMethod.Stub implements HandlerCaller.Callback { private static final String TAG = "InputMethodWrapper"; - private static final boolean DEBUG = false; private static final int DO_DUMP = 1; private static final int DO_ATTACH_TOKEN = 10; @@ -78,20 +78,29 @@ class IInputMethodWrapper extends IInputMethod.Stub } // NOTE: we should have a cache of these. - static class InputMethodSessionCallbackWrapper implements InputMethod.SessionCallback { + static final class InputMethodSessionCallbackWrapper implements InputMethod.SessionCallback { final Context mContext; + final InputChannel mChannel; final IInputSessionCallback mCb; - InputMethodSessionCallbackWrapper(Context context, IInputSessionCallback cb) { + + InputMethodSessionCallbackWrapper(Context context, InputChannel channel, + IInputSessionCallback cb) { mContext = context; + mChannel = channel; mCb = cb; } + + @Override public void sessionCreated(InputMethodSession session) { try { if (session != null) { IInputMethodSessionWrapper wrap = - new IInputMethodSessionWrapper(mContext, session); + new IInputMethodSessionWrapper(mContext, session, mChannel); mCb.sessionCreated(wrap); } else { + if (mChannel != null) { + mChannel.dispose(); + } mCb.sessionCreated(null); } } catch (RemoteException e) { @@ -112,6 +121,7 @@ class IInputMethodWrapper extends IInputMethod.Stub return mInputMethod.get(); } + @Override public void executeMessage(Message msg) { InputMethod inputMethod = mInputMethod.get(); // Need a valid reference to the inputMethod for everything except a dump. @@ -174,8 +184,11 @@ class IInputMethodWrapper extends IInputMethod.Stub return; } case DO_CREATE_SESSION: { + SomeArgs args = (SomeArgs)msg.obj; inputMethod.createSession(new InputMethodSessionCallbackWrapper( - mCaller.mContext, (IInputSessionCallback)msg.obj)); + mCaller.mContext, (InputChannel)args.arg1, + (IInputSessionCallback)args.arg2)); + args.recycle(); return; } case DO_SET_SESSION_ENABLED: @@ -197,8 +210,9 @@ class IInputMethodWrapper extends IInputMethod.Stub } Log.w(TAG, "Unhandled message code: " + msg.what); } - - @Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { + + @Override + protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { AbstractInputMethodService target = mTarget.get(); if (target == null) { return; @@ -224,10 +238,12 @@ class IInputMethodWrapper extends IInputMethod.Stub } } + @Override public void attachToken(IBinder token) { mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_ATTACH_TOKEN, token)); } - + + @Override public void bindInput(InputBinding binding) { InputConnection ic = new InputConnectionWrapper( IInputContext.Stub.asInterface(binding.getConnectionToken())); @@ -235,24 +251,30 @@ class IInputMethodWrapper extends IInputMethod.Stub mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_INPUT_CONTEXT, nu)); } + @Override public void unbindInput() { mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_UNSET_INPUT_CONTEXT)); } + @Override public void startInput(IInputContext inputContext, EditorInfo attribute) { mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_START_INPUT, inputContext, attribute)); } + @Override public void restartInput(IInputContext inputContext, EditorInfo attribute) { mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_RESTART_INPUT, inputContext, attribute)); } - public void createSession(IInputSessionCallback callback) { - mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_CREATE_SESSION, callback)); + @Override + public void createSession(InputChannel channel, IInputSessionCallback callback) { + mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_CREATE_SESSION, + channel, callback)); } + @Override public void setSessionEnabled(IInputMethodSession session, boolean enabled) { try { InputMethodSession ls = ((IInputMethodSessionWrapper) @@ -263,7 +285,8 @@ class IInputMethodWrapper extends IInputMethod.Stub Log.w(TAG, "Incoming session not of correct type: " + session, e); } } - + + @Override public void revokeSession(IInputMethodSession session) { try { InputMethodSession ls = ((IInputMethodSessionWrapper) @@ -273,17 +296,20 @@ class IInputMethodWrapper extends IInputMethod.Stub Log.w(TAG, "Incoming session not of correct type: " + session, e); } } - + + @Override public void showSoftInput(int flags, ResultReceiver resultReceiver) { mCaller.executeOrSendMessage(mCaller.obtainMessageIO(DO_SHOW_SOFT_INPUT, flags, resultReceiver)); } - + + @Override public void hideSoftInput(int flags, ResultReceiver resultReceiver) { mCaller.executeOrSendMessage(mCaller.obtainMessageIO(DO_HIDE_SOFT_INPUT, flags, resultReceiver)); } + @Override public void changeInputMethodSubtype(InputMethodSubtype subtype) { mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_CHANGE_INPUTMETHOD_SUBTYPE, subtype)); |