diff options
| author | 2015-09-01 11:41:35 -0700 | |
|---|---|---|
| committer | 2015-09-08 10:48:36 -0700 | |
| commit | 976724e81bca33dc48347f88633a37a195b9e4ea (patch) | |
| tree | e825f2a49e4fc1eb3128e30661c58e7b8b6cc4f8 | |
| parent | 55a309f8e2a972a2f0ef0cd86736d3c2f47a75f6 (diff) | |
Feed mouse and keyboard events to EventStreamTransformation
Updates AccessibilityInputFilter to pass keyboard and mouse events
through enabed EventStreamTransformations.
This is done in preparation for implementing Autoclick on mouse stop
feature, which depends on those events.
Existing EventStreamTransformation implementstions are modified to
non touchscreen motion events and key board events.
Adds stub EventStreamTransformation (AutoclickController) that will
be used to implement autoclick feature.
Implements key event filtering as a separate EventStreamTransformation
(instead of doing it directly in AccessibilityInputFilter).
Introduces private EventStreamState classes to AccessibilityInputFilter,
which keep track of whether event sequences for different input sources
have started, and help reduce code duplication when determining whether
an event should be fed to registered EventStreamTransformers.
BUG=23113412
Change-Id: If115799bbe4debce48689370ff5ea9fa6dab9639
6 files changed, 529 insertions, 101 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java index 9f080cabd5ff..87a0b808f573 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java @@ -63,6 +63,13 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo */ static final int FLAG_FEATURE_FILTER_KEY_EVENTS = 0x00000004; + /** + * Flag for enabling "Automatically click on mouse stop" feature. + * + * @see #setEnabledFeatures(int) + */ + static final int FLAG_FEATURE_AUTOCLICK = 0x00000008; + private final Runnable mProcessBatchedEventsRunnable = new Runnable() { @Override public void run() { @@ -88,8 +95,6 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo private final Choreographer mChoreographer; - private int mCurrentTouchDeviceId; - private boolean mInstalled; private int mEnabledFeatures; @@ -98,17 +103,19 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo private ScreenMagnifier mScreenMagnifier; + private AutoclickController mAutoclickController; + + private KeyboardInterceptor mKeyboardInterceptor; + private EventStreamTransformation mEventHandler; private MotionEventHolder mEventQueue; - private boolean mMotionEventSequenceStarted; - - private boolean mHoverEventSequenceStarted; + private EventStreamState mMouseStreamState; - private boolean mKeyEventSequenceStarted; + private EventStreamState mTouchScreenStreamState; - private boolean mFilterKeyEvents; + private EventStreamState mKeyboardStreamState; AccessibilityInputFilter(Context context, AccessibilityManagerService service) { super(context.getMainLooper()); @@ -142,89 +149,95 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo @Override public void onInputEvent(InputEvent event, int policyFlags) { if (DEBUG) { - Slog.d(TAG, "Received event: " + event + ", policyFlags=0x" + Slog.d(TAG, "Received event: " + event + ", policyFlags=0x" + Integer.toHexString(policyFlags)); } - if (event instanceof MotionEvent - && event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)) { - MotionEvent motionEvent = (MotionEvent) event; - onMotionEvent(motionEvent, policyFlags); - } else if (event instanceof KeyEvent - && event.isFromSource(InputDevice.SOURCE_KEYBOARD)) { - KeyEvent keyEvent = (KeyEvent) event; - onKeyEvent(keyEvent, policyFlags); - } else { - super.onInputEvent(event, policyFlags); - } - } - private void onMotionEvent(MotionEvent event, int policyFlags) { if (mEventHandler == null) { super.onInputEvent(event, policyFlags); return; } - if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) == 0) { - mMotionEventSequenceStarted = false; - mHoverEventSequenceStarted = false; - mEventHandler.clear(); + + EventStreamState state = getEventStreamState(event); + if (state == null) { super.onInputEvent(event, policyFlags); return; } - final int deviceId = event.getDeviceId(); - if (mCurrentTouchDeviceId != deviceId) { - mCurrentTouchDeviceId = deviceId; - mMotionEventSequenceStarted = false; - mHoverEventSequenceStarted = false; - mEventHandler.clear(); - } - if (mCurrentTouchDeviceId < 0) { + + int eventSource = event.getSource(); + if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) == 0) { + state.reset(); + mEventHandler.clearEvents(eventSource); super.onInputEvent(event, policyFlags); return; } - // We do not handle scroll events. - if (event.getActionMasked() == MotionEvent.ACTION_SCROLL) { + + if (state.updateDeviceId(event.getDeviceId())) { + mEventHandler.clearEvents(eventSource); + } + + if (!state.deviceIdValid()) { super.onInputEvent(event, policyFlags); return; } - // Wait for a down touch event to start processing. - if (event.isTouchEvent()) { - if (!mMotionEventSequenceStarted) { - if (event.getActionMasked() != MotionEvent.ACTION_DOWN) { - return; - } - mMotionEventSequenceStarted = true; - } - } else { - // Wait for an enter hover event to start processing. - if (!mHoverEventSequenceStarted) { - if (event.getActionMasked() != MotionEvent.ACTION_HOVER_ENTER) { - return; - } - mHoverEventSequenceStarted = true; - } + + if (event instanceof MotionEvent) { + MotionEvent motionEvent = (MotionEvent) event; + processMotionEvent(state, motionEvent, policyFlags); + } else if (event instanceof KeyEvent) { + KeyEvent keyEvent = (KeyEvent) event; + processKeyEvent(state, keyEvent, policyFlags); } - batchMotionEvent((MotionEvent) event, policyFlags); } - private void onKeyEvent(KeyEvent event, int policyFlags) { - if (!mFilterKeyEvents) { + /** + * Gets current event stream state associated with an input event. + * @return The event stream state that should be used for the event. Null if the event should + * not be handled by #AccessibilityInputFilter. + */ + private EventStreamState getEventStreamState(InputEvent event) { + if (event instanceof MotionEvent) { + if (event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)) { + if (mTouchScreenStreamState == null) { + mTouchScreenStreamState = new TouchScreenEventStreamState(); + } + return mTouchScreenStreamState; + } + if (event.isFromSource(InputDevice.SOURCE_MOUSE)) { + if (mMouseStreamState == null) { + mMouseStreamState = new MouseEventStreamState(); + } + return mMouseStreamState; + } + } else if (event instanceof KeyEvent) { + if (event.isFromSource(InputDevice.SOURCE_KEYBOARD)) { + if (mKeyboardStreamState == null) { + mKeyboardStreamState = new KeyboardEventStreamState(); + } + return mKeyboardStreamState; + } + } + return null; + } + + private void processMotionEvent(EventStreamState state, MotionEvent event, int policyFlags) { + if (!state.shouldProcessScroll() && event.getActionMasked() == MotionEvent.ACTION_SCROLL) { super.onInputEvent(event, policyFlags); return; } - if ((policyFlags & WindowManagerPolicy.FLAG_PASS_TO_USER) == 0) { - mKeyEventSequenceStarted = false; - super.onInputEvent(event, policyFlags); + + if (!state.shouldProcessMotionEvent(event)) { return; } - // Wait for a down key event to start processing. - if (!mKeyEventSequenceStarted) { - if (event.getAction() != KeyEvent.ACTION_DOWN) { - super.onInputEvent(event, policyFlags); - return; - } - mKeyEventSequenceStarted = true; + + batchMotionEvent(event, policyFlags); + } + + private void processKeyEvent(EventStreamState state, KeyEvent event, int policyFlags) { + if (!state.shouldProcessKeyEvent(event)) { + return; } - mAms.notifyKeyEvent(event, policyFlags); + mEventHandler.onKeyEvent(event, policyFlags); } private void scheduleProcessBatchedEvents() { @@ -293,6 +306,11 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo } @Override + public void onKeyEvent(KeyEvent event, int policyFlags) { + sendInputEvent(event, policyFlags); + } + + @Override public void onAccessibilityEvent(AccessibilityEvent event) { // TODO Implement this to inject the accessibility event // into the accessibility manager service similarly @@ -305,7 +323,7 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo } @Override - public void clear() { + public void clearEvents(int inputSource) { /* do nothing */ } @@ -329,43 +347,77 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo } private void enableFeatures() { - mMotionEventSequenceStarted = false; - mHoverEventSequenceStarted = false; - if ((mEnabledFeatures & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0) { - mEventHandler = mScreenMagnifier = new ScreenMagnifier(mContext, - Display.DEFAULT_DISPLAY, mAms); - mEventHandler.setNext(this); + resetStreamState(); + + if ((mEnabledFeatures & FLAG_FEATURE_AUTOCLICK) != 0) { + mAutoclickController = new AutoclickController(mContext); + addFirstEventHandler(mAutoclickController); } + if ((mEnabledFeatures & FLAG_FEATURE_TOUCH_EXPLORATION) != 0) { mTouchExplorer = new TouchExplorer(mContext, mAms); - mTouchExplorer.setNext(this); - if (mEventHandler != null) { - mEventHandler.setNext(mTouchExplorer); - } else { - mEventHandler = mTouchExplorer; - } + addFirstEventHandler(mTouchExplorer); + } + + if ((mEnabledFeatures & FLAG_FEATURE_SCREEN_MAGNIFIER) != 0) { + mScreenMagnifier = new ScreenMagnifier(mContext, + Display.DEFAULT_DISPLAY, mAms); + addFirstEventHandler(mScreenMagnifier); } + if ((mEnabledFeatures & FLAG_FEATURE_FILTER_KEY_EVENTS) != 0) { - mFilterKeyEvents = true; + mKeyboardInterceptor = new KeyboardInterceptor(mAms); + addFirstEventHandler(mKeyboardInterceptor); } } + /** + * Adds an event handler to the event handler chain. The handler is added at the beginning of + * the chain. + * + * @param handler The handler to be added to the event handlers list. + */ + private void addFirstEventHandler(EventStreamTransformation handler) { + if (mEventHandler != null) { + handler.setNext(mEventHandler); + } else { + handler.setNext(this); + } + mEventHandler = handler; + } + void disableFeatures() { + if (mAutoclickController != null) { + mAutoclickController.onDestroy(); + mAutoclickController = null; + } if (mTouchExplorer != null) { - mTouchExplorer.clear(); mTouchExplorer.onDestroy(); mTouchExplorer = null; } if (mScreenMagnifier != null) { - mScreenMagnifier.clear(); mScreenMagnifier.onDestroy(); mScreenMagnifier = null; } + if (mKeyboardInterceptor != null) { + mKeyboardInterceptor.onDestroy(); + mKeyboardInterceptor = null; + } + mEventHandler = null; - mKeyEventSequenceStarted = false; - mMotionEventSequenceStarted = false; - mHoverEventSequenceStarted = false; - mFilterKeyEvents = false; + resetStreamState(); + } + + void resetStreamState() { + if (mTouchScreenStreamState != null) { + mTouchScreenStreamState.reset(); + } + if (mMouseStreamState != null) { + mMouseStreamState.reset(); + } + if (mKeyboardStreamState != null) { + mKeyboardStreamState.reset(); + } } @Override @@ -402,4 +454,171 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo sPool.release(this); } } + + /** + * Keeps state of event streams observed for an input device with a certain source. + * Provides information about whether motion and key events should be processed by accessibility + * #EventStreamTransformations. Base implementation describes behaviour for event sources that + * whose events should not be handled by a11y event stream transformations. + */ + private static class EventStreamState { + private int mDeviceId; + + EventStreamState() { + mDeviceId = -1; + } + + /** + * Updates the ID of the device associated with the state. If the ID changes, resets + * internal state. + * + * @param deviceId Updated input device ID. + * @return Whether the device ID has changed. + */ + public boolean updateDeviceId(int deviceId) { + if (mDeviceId == deviceId) { + return false; + } + // Reset clears internal state, so make sure it's called before |mDeviceId| is updated. + reset(); + mDeviceId = deviceId; + return true; + } + + /** + * @return Whether device ID is valid. + */ + public boolean deviceIdValid() { + return mDeviceId >= 0; + } + + /** + * Resets the event stream state. + */ + public void reset() { + mDeviceId = -1; + } + + /** + * @return Whether scroll events for device should be handled by event transformations. + */ + public boolean shouldProcessScroll() { + return false; + } + + /** + * @param event An observed motion event. + * @return Whether the event should be handled by event transformations. + */ + public boolean shouldProcessMotionEvent(MotionEvent event) { + return false; + } + + /** + * @param event An observed key event. + * @return Whether the event should be handled by event transformations. + */ + public boolean shouldProcessKeyEvent(KeyEvent event) { + return false; + } + } + + /** + * Keeps state of stream of events from a mouse device. + */ + private static class MouseEventStreamState extends EventStreamState { + private boolean mMotionSequenceStarted; + + public MouseEventStreamState() { + reset(); + } + + @Override + final public void reset() { + super.reset(); + mMotionSequenceStarted = false; + } + + @Override + final public boolean shouldProcessScroll() { + return true; + } + + @Override + final public boolean shouldProcessMotionEvent(MotionEvent event) { + if (mMotionSequenceStarted) { + return true; + } + // Wait for down or move event to start processing mouse events. + int action = event.getActionMasked(); + mMotionSequenceStarted = + action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_HOVER_MOVE; + return mMotionSequenceStarted; + } + } + + /** + * Keeps state of stream of events from a touch screen device. + */ + private static class TouchScreenEventStreamState extends EventStreamState { + private boolean mTouchSequenceStarted; + private boolean mHoverSequenceStarted; + + public TouchScreenEventStreamState() { + reset(); + } + + @Override + final public void reset() { + super.reset(); + mTouchSequenceStarted = false; + mHoverSequenceStarted = false; + } + + @Override + final public boolean shouldProcessMotionEvent(MotionEvent event) { + // Wait for a down touch event to start processing. + if (event.isTouchEvent()) { + if (mTouchSequenceStarted) { + return true; + } + mTouchSequenceStarted = event.getActionMasked() == MotionEvent.ACTION_DOWN; + return mTouchSequenceStarted; + } + + // Wait for an enter hover event to start processing. + if (mHoverSequenceStarted) { + return true; + } + mHoverSequenceStarted = event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER; + return mHoverSequenceStarted; + } + } + + /** + * Keeps state of stream of events from a keyboard device. + */ + private static class KeyboardEventStreamState extends EventStreamState { + private boolean mEventSequenceStarted; + + public KeyboardEventStreamState() { + reset(); + } + + @Override + final public void reset() { + super.reset(); + mEventSequenceStarted = false; + } + + @Override + final public boolean shouldProcessKeyEvent(KeyEvent event) { + // Wait for a down key event to start processing. + if (mEventSequenceStarted) { + return true; + } + mEventSequenceStarted = event.getAction() == KeyEvent.ACTION_DOWN; + return mEventSequenceStarted; + } + } } diff --git a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/AutoclickController.java new file mode 100644 index 000000000000..318b7b4dbfc1 --- /dev/null +++ b/services/accessibility/java/com/android/server/accessibility/AutoclickController.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.accessibility; + +import android.content.Context; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.accessibility.AccessibilityEvent; + +/** + * Implements "Automatically click on mouse stop" feature. + * + * If enabled, it will observe motion events from mouse source, and send click event sequence short + * while after mouse stops moving. The click will only be performed if mouse movement had been + * actually detected. + * + * Movement detection has tolerance to jitter that may be caused by poor motor control to prevent: + * <ul> + * <li>Initiating unwanted clicks with no mouse movement.</li> + * <li>Autoclick never occurring after mouse arriving at target.</li> + * </ul> + * + * Non-mouse motion events, key events (excluding modifiers) and non-movement mouse events cancel + * the automatic click. + */ +public class AutoclickController implements EventStreamTransformation { + private EventStreamTransformation mNext; + + public AutoclickController(Context context) {} + + @Override + public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { + // TODO: Implement this. + if (mNext != null) { + mNext.onMotionEvent(event, rawEvent, policyFlags); + } + } + + @Override + public void onKeyEvent(KeyEvent event, int policyFlags) { + // TODO: Implement this. + if (mNext != null) { + mNext.onKeyEvent(event, policyFlags); + } + } + + @Override + public void onAccessibilityEvent(AccessibilityEvent event) { + if (mNext != null) { + mNext.onAccessibilityEvent(event); + } + } + + @Override + public void setNext(EventStreamTransformation next) { + mNext = next; + } + + @Override + public void clearEvents(int inputSource) { + if (mNext != null) { + mNext.clearEvents(inputSource); + } + } + + @Override + public void onDestroy() { + } +} diff --git a/services/accessibility/java/com/android/server/accessibility/EventStreamTransformation.java b/services/accessibility/java/com/android/server/accessibility/EventStreamTransformation.java index 8c93e7b4440d..fdc40984dab4 100644 --- a/services/accessibility/java/com/android/server/accessibility/EventStreamTransformation.java +++ b/services/accessibility/java/com/android/server/accessibility/EventStreamTransformation.java @@ -68,6 +68,14 @@ interface EventStreamTransformation { public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags); /** + * Receives a key event. + * + * @param event The key event. + * @param policyFlags Policy flags for the event. + */ + public void onKeyEvent(KeyEvent event, int policyFlags); + + /** * Receives an accessibility event. * * @param event The accessibility event. @@ -82,9 +90,11 @@ interface EventStreamTransformation { public void setNext(EventStreamTransformation next); /** - * Clears the internal state of this transformation. + * Clears internal state associated with events from specific input source. + * + * @param inputSource The input source class for which transformation state should be cleared. */ - public void clear(); + public void clearEvents(int inputSource); /** * Destroys this transformation. diff --git a/services/accessibility/java/com/android/server/accessibility/KeyboardInterceptor.java b/services/accessibility/java/com/android/server/accessibility/KeyboardInterceptor.java new file mode 100644 index 000000000000..bbb25af5da43 --- /dev/null +++ b/services/accessibility/java/com/android/server/accessibility/KeyboardInterceptor.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.accessibility; + +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.accessibility.AccessibilityEvent; + +/** + * Intercepts key events and forwards them to accessibility manager service. + */ +public class KeyboardInterceptor implements EventStreamTransformation { + private EventStreamTransformation mNext; + private AccessibilityManagerService mAms; + + public KeyboardInterceptor(AccessibilityManagerService service) { + mAms = service; + } + + @Override + public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { + if (mNext != null) { + mNext.onMotionEvent(event, rawEvent, policyFlags); + } + } + + @Override + public void onKeyEvent(KeyEvent event, int policyFlags) { + mAms.notifyKeyEvent(event, policyFlags); + } + + @Override + public void onAccessibilityEvent(AccessibilityEvent event) { + if (mNext != null) { + mNext.onAccessibilityEvent(event); + } + } + + @Override + public void setNext(EventStreamTransformation next) { + mNext = next; + } + + @Override + public void clearEvents(int inputSource) { + if (mNext != null) { + mNext.clearEvents(inputSource); + } + } + + @Override + public void onDestroy() { + } +} diff --git a/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java index b4613d6d811a..37276bdb8145 100644 --- a/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java +++ b/services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java @@ -37,6 +37,8 @@ import android.util.Slog; import android.util.TypedValue; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; +import android.view.InputDevice; +import android.view.KeyEvent; import android.view.MagnificationSpec; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; @@ -325,6 +327,12 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio @Override public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { + if (!event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)) { + if (mNext != null) { + mNext.onMotionEvent(event, rawEvent, policyFlags); + } + return; + } mMagnifiedContentInteractonStateHandler.onMotionEvent(event); switch (mCurrentState) { case STATE_DELEGATING: { @@ -348,6 +356,13 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio } @Override + public void onKeyEvent(KeyEvent event, int policyFlags) { + if (mNext != null) { + mNext.onKeyEvent(event, policyFlags); + } + } + + @Override public void onAccessibilityEvent(AccessibilityEvent event) { if (mNext != null) { mNext.onAccessibilityEvent(event); @@ -360,22 +375,30 @@ public final class ScreenMagnifier implements WindowManagerInternal.Magnificatio } @Override - public void clear() { - mCurrentState = STATE_DETECTING; - mDetectingStateHandler.clear(); - mStateViewportDraggingHandler.clear(); - mMagnifiedContentInteractonStateHandler.clear(); + public void clearEvents(int inputSource) { + if (inputSource == InputDevice.SOURCE_TOUCHSCREEN) { + clear(); + } + if (mNext != null) { - mNext.clear(); + mNext.clearEvents(inputSource); } } @Override public void onDestroy() { + clear(); mScreenStateObserver.destroy(); mWindowManager.setMagnificationCallbacks(null); } + private void clear() { + mCurrentState = STATE_DETECTING; + mDetectingStateHandler.clear(); + mStateViewportDraggingHandler.clear(); + mMagnifiedContentInteractonStateHandler.clear(); + } + private void handleMotionEventStateDelegating(MotionEvent event, MotionEvent rawEvent, int policyFlags) { switch (event.getActionMasked()) { diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java index f18b5ef338aa..85730cdef082 100644 --- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java @@ -29,6 +29,8 @@ import android.graphics.Rect; import android.os.Handler; import android.os.SystemClock; import android.util.Slog; +import android.view.InputDevice; +import android.view.KeyEvent; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; import android.view.MotionEvent.PointerProperties; @@ -253,7 +255,22 @@ class TouchExplorer implements EventStreamTransformation { mScaledGestureDetectionVelocity = (int) (GESTURE_DETECTION_VELOCITY_DIP * density); } - public void clear() { + @Override + public void clearEvents(int inputSource) { + if (inputSource == InputDevice.SOURCE_TOUCHSCREEN) { + clear(); + } + if (mNext != null) { + mNext.clearEvents(inputSource); + } + } + + @Override + public void onDestroy() { + clear(); + } + + private void clear() { // If we have not received an event then we are in initial // state. Therefore, there is not need to clean anything. MotionEvent event = mReceivedPointerTracker.getLastReceivedEvent(); @@ -262,10 +279,6 @@ class TouchExplorer implements EventStreamTransformation { } } - public void onDestroy() { - // TODO: Implement - } - private void clear(MotionEvent event, int policyFlags) { switch (mCurrentState) { case STATE_TOUCH_EXPLORING: { @@ -304,9 +317,6 @@ class TouchExplorer implements EventStreamTransformation { mLongPressingPointerDeltaX = 0; mLongPressingPointerDeltaY = 0; mCurrentState = STATE_TOUCH_EXPLORING; - if (mNext != null) { - mNext.clear(); - } mTouchExplorationInProgress = false; mAms.onTouchInteractionEnd(); } @@ -318,6 +328,13 @@ class TouchExplorer implements EventStreamTransformation { @Override public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { + if (!event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)) { + if (mNext != null) { + mNext.onMotionEvent(event, rawEvent, policyFlags); + } + return; + } + if (DEBUG) { Slog.d(LOG_TAG, "Received event: " + event + ", policyFlags=0x" + Integer.toHexString(policyFlags)); @@ -344,6 +361,14 @@ class TouchExplorer implements EventStreamTransformation { } } + @Override + public void onKeyEvent(KeyEvent event, int policyFlags) { + if (mNext != null) { + mNext.onKeyEvent(event, policyFlags); + } + } + + @Override public void onAccessibilityEvent(AccessibilityEvent event) { final int eventType = event.getEventType(); |