[DO NOT MERGE] Transition to clear state after gesture cancelation.

The agreed-upon behavior has always been that after gesture cancelation, touch explorer would exist in essentially a dead state.
It should not be possible to execute a two-finger passthrough gesture for example after doing an invalid gesture.
This is likely why we see GESTURE_PASSTHROUGH in cases where we expect GESTURE_UNKNOWN.
Fix: 171421786
Bug: 162521649
Test: manual
Change-Id: Idce921c5278dea174ec5dad5cecf046f12ab113d

Change-Id: Ic71246adc613ea60d3f25974e4085814c4b3211d
This commit is contained in:
Ameer Armaly
2020-10-22 07:11:39 -07:00
parent b348567101
commit a9027a7f9f
4 changed files with 19 additions and 7 deletions

View File

@@ -104,9 +104,9 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
// Shared state information.
private TouchState mState;
GestureManifold(Context context, Listener listener, TouchState state) {
GestureManifold(Context context, Listener listener, TouchState state, Handler handler) {
mContext = context;
mHandler = new Handler(context.getMainLooper());
mHandler = handler;
mListener = listener;
mState = state;
mMultiFingerGesturesEnabled = false;

View File

@@ -175,7 +175,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
AccessibilityEvent.TYPE_TOUCH_INTERACTION_END,
mDetermineUserIntentTimeout);
if (detector == null) {
mGestureDetector = new GestureManifold(context, this, mState);
mGestureDetector = new GestureManifold(context, this, mState, mHandler);
} else {
mGestureDetector = detector;
}
@@ -353,7 +353,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
public boolean onGestureStarted() {
// We have to perform gesture detection, so
// clear the current state and try to detect.
mState.startGestureDetecting();
mSendHoverEnterAndMoveDelayed.cancel();
mSendHoverExitDelayed.cancel();
mExitGestureDetectionModeDelayed.post();
@@ -1107,7 +1106,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
private boolean shouldPerformGestureDetection(MotionEvent event) {
if (mState.isDelegating()) {
if (mState.isDelegating() || mState.isDragging()) {
return false;
}
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
@@ -1200,6 +1199,15 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
public void run() {
if (mReceivedPointerTracker.getReceivedPointerDownCount() > 1) {
// Multi-finger touch exploration doesn't make sense.
Slog.e(
LOG_TAG,
"Attempted touch exploration with "
+ mReceivedPointerTracker.getReceivedPointerDownCount()
+ " pointers down.");
return;
}
// Send an accessibility event to announce the touch exploration start.
mDispatcher.sendAccessibilityEvent(
AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);

View File

@@ -208,7 +208,9 @@ public class TouchState {
startGestureDetecting();
break;
case AccessibilityEvent.TYPE_GESTURE_DETECTION_END:
startTouchInteracting();
// Clear to make sure that we don't accidentally execute passthrough, and that we
// are ready for the next interaction.
clear();
break;
default:
break;

View File

@@ -26,6 +26,7 @@ import android.accessibilityservice.AccessibilityService;
import android.content.Context;
import android.graphics.Point;
import android.graphics.PointF;
import android.os.Handler;
import android.view.MotionEvent;
import androidx.test.InstrumentationRegistry;
@@ -56,7 +57,8 @@ public class GestureManifoldTest {
// Construct a testable GestureManifold.
mResultListener = mock(GestureManifold.Listener.class);
mState = new TouchState();
mManifold = new GestureManifold(context, mResultListener, mState);
Handler handler = new Handler(context.getMainLooper());
mManifold = new GestureManifold(context, mResultListener, mState, handler);
// Play the role of touch explorer in updating the shared state.
when(mResultListener.onGestureStarted()).thenReturn(onGestureStarted());