summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java389
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AutoclickController.java83
-rw-r--r--services/accessibility/java/com/android/server/accessibility/EventStreamTransformation.java14
-rw-r--r--services/accessibility/java/com/android/server/accessibility/KeyboardInterceptor.java68
-rw-r--r--services/accessibility/java/com/android/server/accessibility/ScreenMagnifier.java35
-rw-r--r--services/accessibility/java/com/android/server/accessibility/TouchExplorer.java41
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();