diff options
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(); |