diff options
| author | Mita Yun <mitayun@google.com> | 2012-12-06 17:18:25 -0800 |
|---|---|---|
| committer | Mita Yun <mitayun@google.com> | 2012-12-06 18:11:32 -0800 |
| commit | ed218c706d9e91e75b94c448cee2e6150aaee57f (patch) | |
| tree | e3a886680edf70b22df31d46d1948121f38de614 /core | |
| parent | c56a57f7d775e7b097c62f9e8fb809467dc5cf0c (diff) | |
| download | frameworks_base-ed218c706d9e91e75b94c448cee2e6150aaee57f.zip frameworks_base-ed218c706d9e91e75b94c448cee2e6150aaee57f.tar.gz frameworks_base-ed218c706d9e91e75b94c448cee2e6150aaee57f.tar.bz2 | |
Use asynchronous messages for input method events.
Improves the throughput of IME event handling by ensuring that
input events do not get serialized behind UI traversal and
drawing messages such as when the UI is animating.
Added support for creating an asynchronous Handler as part of a
HandlerCaller. It turns out we should be using an asynchronous
Handler not only in IME dispatch but also in accessibility and
wallpaper events where HandlerCaller is used. So fixed those
services to also use an asynchronous Handler.
Change-Id: I0b19140c9d5ca6ee300c1a150c48312fd55ed8eb
Diffstat (limited to 'core')
6 files changed, 53 insertions, 48 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index b0bad07..9d6ee80 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -556,7 +556,7 @@ public abstract class AccessibilityService extends Service { public IAccessibilityServiceClientWrapper(Context context, Looper looper, Callbacks callback) { mCallback = callback; - mCaller = new HandlerCaller(context, looper, this); + mCaller = new HandlerCaller(context, looper, this, true /*asyncHandler*/); } public void setConnection(IAccessibilityServiceConnection connection, int connectionId) { diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java index 5324f81..d78262b 100644 --- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java @@ -70,7 +70,8 @@ class IInputMethodSessionWrapper extends IInputMethodSession.Stub public IInputMethodSessionWrapper(Context context, InputMethodSession inputMethodSession) { - mCaller = new HandlerCaller(context, this); + mCaller = new HandlerCaller(context, null, + this, true /*asyncHandler*/); mInputMethodSession = inputMethodSession; } diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java index 5275314..2d67875 100644 --- a/core/java/android/inputmethodservice/IInputMethodWrapper.java +++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java @@ -102,7 +102,8 @@ class IInputMethodWrapper extends IInputMethod.Stub public IInputMethodWrapper(AbstractInputMethodService context, InputMethod inputMethod) { mTarget = new WeakReference<AbstractInputMethodService>(context); - mCaller = new HandlerCaller(context.getApplicationContext(), this); + mCaller = new HandlerCaller(context.getApplicationContext(), null, + this, true /*asyncHandler*/); mInputMethod = new WeakReference<InputMethod>(inputMethod); mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion; } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 6d5705d..477356e 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -967,7 +967,7 @@ public abstract class WallpaperService extends Service { mCaller = new HandlerCaller(context, mCallbackLooper != null ? mCallbackLooper : context.getMainLooper(), - this); + this, true /*asyncHandler*/); mConnection = conn; mWindowToken = windowToken; mWindowType = windowType; diff --git a/core/java/android/view/SimulatedTrackball.java b/core/java/android/view/SimulatedTrackball.java index b917371..0eb197e 100644 --- a/core/java/android/view/SimulatedTrackball.java +++ b/core/java/android/view/SimulatedTrackball.java @@ -40,7 +40,7 @@ class SimulatedTrackball { private static final int MAX_TAP_TIME = 250; // Where the cutoff is for determining an edge swipe private static final float EDGE_SWIPE_THRESHOLD = 0.9f; - private static final int FLICK_MSG_ID = 313; + private static final int MSG_FLICK = 313; // TODO: Pass touch slop from the input device private static final int TOUCH_SLOP = 30; @@ -75,8 +75,11 @@ class SimulatedTrackball { // Has the TouchSlop constraint been invalidated private boolean mAlwaysInTapRegion = true; - // Most recent event. Used to determine what device sent the event. - private MotionEvent mRecentEvent; + // Information from the most recent event. + // Used to determine what device sent the event during a fling. + private int mLastSource; + private int mLastMetaState; + private int mLastDeviceId; // TODO: Currently using screen dimensions tuned to a Galaxy Nexus, need to // read this from a config file instead @@ -101,33 +104,34 @@ class SimulatedTrackball { mTouchSlopSquared = mTouchSlop * mTouchSlop; } - private final Handler mHandler = new Handler(new Callback() { + private final Handler mHandler = new Handler(true /*async*/) { @Override - public boolean handleMessage(Message msg) { - if (msg.what != FLICK_MSG_ID) - return false; + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_FLICK: { + final long time = SystemClock.uptimeMillis(); + ViewRootImpl viewroot = (ViewRootImpl) msg.obj; + // Send the key + viewroot.enqueueInputEvent(new KeyEvent(time, time, + KeyEvent.ACTION_DOWN, msg.arg2, 0, mLastMetaState, + mLastDeviceId, 0, KeyEvent.FLAG_FALLBACK, mLastSource)); + viewroot.enqueueInputEvent(new KeyEvent(time, time, + KeyEvent.ACTION_UP, msg.arg2, 0, mLastMetaState, + mLastDeviceId, 0, KeyEvent.FLAG_FALLBACK, mLastSource)); - final long time = SystemClock.uptimeMillis(); - ViewRootImpl viewroot = (ViewRootImpl) msg.obj; - // Send the key - viewroot.enqueueInputEvent(new KeyEvent(time, time, - KeyEvent.ACTION_DOWN, msg.arg2, 0, mRecentEvent.getMetaState(), - mRecentEvent.getDeviceId(), 0, - KeyEvent.FLAG_FALLBACK, mRecentEvent.getSource())); - viewroot.enqueueInputEvent(new KeyEvent(time, time, - KeyEvent.ACTION_UP, msg.arg2, 0, mRecentEvent.getMetaState(), - mRecentEvent.getDeviceId(), 0, - KeyEvent.FLAG_FALLBACK, mRecentEvent.getSource())); - Message msgCopy = Message.obtain(msg); - // Increase the delay by the decay factor - msgCopy.arg1 = (int) Math.ceil(mFlickDecay * msgCopy.arg1); - if (msgCopy.arg1 <= mMaxRepeatDelay) { - // Send the key again in arg1 milliseconds - mHandler.sendMessageDelayed(msgCopy, msgCopy.arg1); + // Increase the delay by the decay factor and resend + final int delay = (int) Math.ceil(mFlickDecay * msg.arg1); + if (delay <= mMaxRepeatDelay) { + Message msgCopy = Message.obtain(msg); + msgCopy.arg1 = delay; + msgCopy.setAsynchronous(true); + mHandler.sendMessageDelayed(msgCopy, delay); + } + break; + } } - return false; } - }); + }; public void updateTrackballDirection(ViewRootImpl viewroot, MotionEvent event) { // Store what time the touchpad event occurred @@ -148,7 +152,7 @@ class SimulatedTrackball { mEdgeSwipePossible = true; } // Clear any flings - mHandler.removeMessages(FLICK_MSG_ID); + mHandler.removeMessages(MSG_FLICK); break; case MotionEvent.ACTION_MOVE: @@ -245,15 +249,20 @@ class SimulatedTrackball { if (mMinFlickDistanceSquared <= xMoveSquared + yMoveSquared && time - mLastTouchPadEventTimeMs <= MAX_TAP_TIME && mKeySendRateMs <= mMaxRepeatDelay && mKeySendRateMs > 0) { - Message message = Message.obtain(mHandler, FLICK_MSG_ID, + mLastDeviceId = event.getDeviceId(); + mLastSource = event.getSource(); + mLastMetaState = event.getMetaState(); + + Message message = Message.obtain(mHandler, MSG_FLICK, mKeySendRateMs, mLastKeySent, viewroot); - mRecentEvent = event; + message.setAsynchronous(true); mHandler.sendMessageDelayed(message, mKeySendRateMs); } } mEdgeSwipePossible = false; break; } + // Store touch event position and time mLastTouchPadEventTimeMs = time; mLastTouchpadXPosition = event.getX(); diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java index 84699dc..b442ff5 100644 --- a/core/java/com/android/internal/os/HandlerCaller.java +++ b/core/java/com/android/internal/os/HandlerCaller.java @@ -24,38 +24,32 @@ import android.os.Message; public class HandlerCaller { public final Context mContext; - + final Looper mMainLooper; final Handler mH; final Callback mCallback; class MyHandler extends Handler { - MyHandler(Looper looper) { - super(looper); + MyHandler(Looper looper, boolean async) { + super(looper, null, async); } - + @Override public void handleMessage(Message msg) { mCallback.executeMessage(msg); } } - + public interface Callback { public void executeMessage(Message msg); } - - public HandlerCaller(Context context, Callback callback) { - mContext = context; - mMainLooper = context.getMainLooper(); - mH = new MyHandler(mMainLooper); - mCallback = callback; - } - public HandlerCaller(Context context, Looper looper, Callback callback) { + public HandlerCaller(Context context, Looper looper, Callback callback, + boolean asyncHandler) { mContext = context; - mMainLooper = looper; - mH = new MyHandler(mMainLooper); + mMainLooper = looper != null ? looper : context.getMainLooper(); + mH = new MyHandler(mMainLooper, asyncHandler); mCallback = callback; } |
