Merge "Ignore the closing MotionEvent of swipe gestures for falsing" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
09262ed09d
@@ -38,6 +38,7 @@ import javax.inject.Inject;
|
||||
public class FalsingDataProvider {
|
||||
|
||||
private static final long MOTION_EVENT_AGE_MS = 1000;
|
||||
private static final long DROP_EVENT_THRESHOLD_MS = 50;
|
||||
private static final float THREE_HUNDRED_SIXTY_DEG = (float) (2 * Math.PI);
|
||||
|
||||
private final int mWidthPixels;
|
||||
@@ -60,6 +61,7 @@ public class FalsingDataProvider {
|
||||
private float mAngle = 0;
|
||||
private MotionEvent mFirstRecentMotionEvent;
|
||||
private MotionEvent mLastMotionEvent;
|
||||
private boolean mDropLastEvent;
|
||||
private boolean mJustUnlockedWithFace;
|
||||
private boolean mA11YAction;
|
||||
|
||||
@@ -95,6 +97,12 @@ public class FalsingDataProvider {
|
||||
// Ensure prior gesture was completed. May be a no-op.
|
||||
completePriorGesture();
|
||||
}
|
||||
|
||||
// Drop the gesture closing event if it is close in time to a previous ACTION_MOVE event.
|
||||
// The reason is that the closing ACTION_UP event of a swipe can be a bit offseted from the
|
||||
// previous ACTION_MOVE event and when it happens, it makes some classifiers fail.
|
||||
mDropLastEvent = shouldDropEvent(motionEvent);
|
||||
|
||||
mRecentMotionEvents.addAll(motionEvents);
|
||||
|
||||
FalsingClassifier.logVerbose("Size: " + mRecentMotionEvents.size());
|
||||
@@ -129,6 +137,7 @@ public class FalsingDataProvider {
|
||||
mPriorMotionEvents = mRecentMotionEvents;
|
||||
mRecentMotionEvents = new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS);
|
||||
}
|
||||
mDropLastEvent = false;
|
||||
mA11YAction = false;
|
||||
}
|
||||
|
||||
@@ -150,8 +159,18 @@ public class FalsingDataProvider {
|
||||
return mYdpi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link MotionEvent}s of the most recent gesture.
|
||||
*
|
||||
* Note that this list may not include the last recorded event.
|
||||
* @see #mDropLastEvent
|
||||
*/
|
||||
public List<MotionEvent> getRecentMotionEvents() {
|
||||
return mRecentMotionEvents;
|
||||
if (!mDropLastEvent || mRecentMotionEvents.isEmpty()) {
|
||||
return mRecentMotionEvents;
|
||||
} else {
|
||||
return mRecentMotionEvents.subList(0, mRecentMotionEvents.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public List<MotionEvent> getPriorMotionEvents() {
|
||||
@@ -169,7 +188,12 @@ public class FalsingDataProvider {
|
||||
return mFirstRecentMotionEvent;
|
||||
}
|
||||
|
||||
/** Get the last recorded {@link MotionEvent}. */
|
||||
/**
|
||||
* Get the last {@link MotionEvent} of the most recent gesture.
|
||||
*
|
||||
* Note that this may be the event prior to the last recorded event.
|
||||
* @see #mDropLastEvent
|
||||
*/
|
||||
public MotionEvent getLastMotionEvent() {
|
||||
recalculateData();
|
||||
return mLastMotionEvent;
|
||||
@@ -236,12 +260,13 @@ public class FalsingDataProvider {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mRecentMotionEvents.isEmpty()) {
|
||||
List<MotionEvent> recentMotionEvents = getRecentMotionEvents();
|
||||
if (recentMotionEvents.isEmpty()) {
|
||||
mFirstRecentMotionEvent = null;
|
||||
mLastMotionEvent = null;
|
||||
} else {
|
||||
mFirstRecentMotionEvent = mRecentMotionEvents.get(0);
|
||||
mLastMotionEvent = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1);
|
||||
mFirstRecentMotionEvent = recentMotionEvents.get(0);
|
||||
mLastMotionEvent = recentMotionEvents.get(recentMotionEvents.size() - 1);
|
||||
}
|
||||
|
||||
calculateAngleInternal();
|
||||
@@ -249,6 +274,17 @@ public class FalsingDataProvider {
|
||||
mDirty = false;
|
||||
}
|
||||
|
||||
private boolean shouldDropEvent(MotionEvent event) {
|
||||
if (mRecentMotionEvents.size() < 3) return false;
|
||||
|
||||
MotionEvent lastEvent = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1);
|
||||
boolean isCompletingGesture = event.getActionMasked() == MotionEvent.ACTION_UP
|
||||
&& lastEvent.getActionMasked() == MotionEvent.ACTION_MOVE;
|
||||
boolean isRecentEvent =
|
||||
event.getEventTime() - lastEvent.getEventTime() < DROP_EVENT_THRESHOLD_MS;
|
||||
return isCompletingGesture && isRecentEvent;
|
||||
}
|
||||
|
||||
private void calculateAngleInternal() {
|
||||
if (mRecentMotionEvents.size() < 2) {
|
||||
mAngle = Float.MAX_VALUE;
|
||||
|
||||
@@ -183,7 +183,7 @@ public class TimeLimitedMotionEventBuffer implements List<MotionEvent> {
|
||||
|
||||
@Override
|
||||
public List<MotionEvent> subList(int fromIndex, int toIndex) {
|
||||
throw new UnsupportedOperationException();
|
||||
return mMotionEvents.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
class Iter implements ListIterator<MotionEvent> {
|
||||
|
||||
@@ -94,7 +94,9 @@ public class DistanceClassifierTest extends ClassifierTest {
|
||||
mClassifier.onTouchEvent(appendMoveEvent(1, 16, 3));
|
||||
mClassifier.onTouchEvent(appendMoveEvent(1, 17, 300));
|
||||
mClassifier.onTouchEvent(appendMoveEvent(1, 18, 301));
|
||||
mClassifier.onTouchEvent(appendUpEvent(1, 19, 501));
|
||||
mClassifier.onTouchEvent(appendMoveEvent(1, 19, 501));
|
||||
mClassifier.onTouchEvent(appendUpEvent(1, 19, 501)); //event will be dropped
|
||||
|
||||
assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@@ -75,16 +75,17 @@ public class FalsingDataProviderTest extends ClassifierTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_trackMotionEvents() {
|
||||
public void test_trackMotionEvents_dropUpEvent() {
|
||||
mDataProvider.onMotionEvent(appendDownEvent(2, 9));
|
||||
mDataProvider.onMotionEvent(appendMoveEvent(4, 7));
|
||||
mDataProvider.onMotionEvent(appendUpEvent(6, 5));
|
||||
mDataProvider.onMotionEvent(appendMoveEvent(6, 5));
|
||||
mDataProvider.onMotionEvent(appendUpEvent(0, 0)); // event will be dropped
|
||||
List<MotionEvent> motionEventList = mDataProvider.getRecentMotionEvents();
|
||||
|
||||
assertThat(motionEventList.size()).isEqualTo(3);
|
||||
assertThat(motionEventList.get(0).getActionMasked()).isEqualTo(MotionEvent.ACTION_DOWN);
|
||||
assertThat(motionEventList.get(1).getActionMasked()).isEqualTo(MotionEvent.ACTION_MOVE);
|
||||
assertThat(motionEventList.get(2).getActionMasked()).isEqualTo(MotionEvent.ACTION_UP);
|
||||
assertThat(motionEventList.get(2).getActionMasked()).isEqualTo(MotionEvent.ACTION_MOVE);
|
||||
assertThat(motionEventList.get(0).getEventTime()).isEqualTo(1L);
|
||||
assertThat(motionEventList.get(1).getEventTime()).isEqualTo(2L);
|
||||
assertThat(motionEventList.get(2).getEventTime()).isEqualTo(3L);
|
||||
@@ -96,6 +97,28 @@ public class FalsingDataProviderTest extends ClassifierTest {
|
||||
assertThat(motionEventList.get(2).getY()).isEqualTo(5f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_trackMotionEvents_keepUpEvent() {
|
||||
mDataProvider.onMotionEvent(appendDownEvent(2, 9));
|
||||
mDataProvider.onMotionEvent(appendMoveEvent(4, 7));
|
||||
mDataProvider.onMotionEvent(appendUpEvent(0, 0, 100));
|
||||
List<MotionEvent> motionEventList = mDataProvider.getRecentMotionEvents();
|
||||
|
||||
assertThat(motionEventList.size()).isEqualTo(3);
|
||||
assertThat(motionEventList.get(0).getActionMasked()).isEqualTo(MotionEvent.ACTION_DOWN);
|
||||
assertThat(motionEventList.get(1).getActionMasked()).isEqualTo(MotionEvent.ACTION_MOVE);
|
||||
assertThat(motionEventList.get(2).getActionMasked()).isEqualTo(MotionEvent.ACTION_UP);
|
||||
assertThat(motionEventList.get(0).getEventTime()).isEqualTo(1L);
|
||||
assertThat(motionEventList.get(1).getEventTime()).isEqualTo(2L);
|
||||
assertThat(motionEventList.get(2).getEventTime()).isEqualTo(100);
|
||||
assertThat(motionEventList.get(0).getX()).isEqualTo(2f);
|
||||
assertThat(motionEventList.get(1).getX()).isEqualTo(4f);
|
||||
assertThat(motionEventList.get(2).getX()).isEqualTo(0f);
|
||||
assertThat(motionEventList.get(0).getY()).isEqualTo(9f);
|
||||
assertThat(motionEventList.get(1).getY()).isEqualTo(7f);
|
||||
assertThat(motionEventList.get(2).getY()).isEqualTo(0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_trackRecentMotionEvents() {
|
||||
mDataProvider.onMotionEvent(appendDownEvent(2, 9, 1));
|
||||
|
||||
@@ -67,6 +67,15 @@ public class ZigZagClassifierTest extends ClassifierTest {
|
||||
assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPass_dropClosingUpEvent() {
|
||||
appendMoveEvent(0, 0);
|
||||
appendMoveEvent(0, 100);
|
||||
appendMoveEvent(0, 200);
|
||||
appendUpEvent(0, 180); // this event would push us over the maxDevianceY
|
||||
assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPass_fewTouchesHorizontal() {
|
||||
assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
|
||||
|
||||
Reference in New Issue
Block a user