Loading packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java +41 −5 Original line number Original line Diff line number Diff line Loading @@ -38,6 +38,7 @@ import javax.inject.Inject; public class FalsingDataProvider { public class FalsingDataProvider { private static final long MOTION_EVENT_AGE_MS = 1000; 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 static final float THREE_HUNDRED_SIXTY_DEG = (float) (2 * Math.PI); private final int mWidthPixels; private final int mWidthPixels; Loading @@ -60,6 +61,7 @@ public class FalsingDataProvider { private float mAngle = 0; private float mAngle = 0; private MotionEvent mFirstRecentMotionEvent; private MotionEvent mFirstRecentMotionEvent; private MotionEvent mLastMotionEvent; private MotionEvent mLastMotionEvent; private boolean mDropLastEvent; private boolean mJustUnlockedWithFace; private boolean mJustUnlockedWithFace; private boolean mA11YAction; private boolean mA11YAction; Loading Loading @@ -95,6 +97,12 @@ public class FalsingDataProvider { // Ensure prior gesture was completed. May be a no-op. // Ensure prior gesture was completed. May be a no-op. completePriorGesture(); 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); mRecentMotionEvents.addAll(motionEvents); FalsingClassifier.logVerbose("Size: " + mRecentMotionEvents.size()); FalsingClassifier.logVerbose("Size: " + mRecentMotionEvents.size()); Loading Loading @@ -129,6 +137,7 @@ public class FalsingDataProvider { mPriorMotionEvents = mRecentMotionEvents; mPriorMotionEvents = mRecentMotionEvents; mRecentMotionEvents = new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS); mRecentMotionEvents = new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS); } } mDropLastEvent = false; mA11YAction = false; mA11YAction = false; } } Loading @@ -150,8 +159,18 @@ public class FalsingDataProvider { return mYdpi; 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() { public List<MotionEvent> getRecentMotionEvents() { if (!mDropLastEvent || mRecentMotionEvents.isEmpty()) { return mRecentMotionEvents; return mRecentMotionEvents; } else { return mRecentMotionEvents.subList(0, mRecentMotionEvents.size() - 1); } } } public List<MotionEvent> getPriorMotionEvents() { public List<MotionEvent> getPriorMotionEvents() { Loading @@ -169,7 +188,12 @@ public class FalsingDataProvider { return mFirstRecentMotionEvent; 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() { public MotionEvent getLastMotionEvent() { recalculateData(); recalculateData(); return mLastMotionEvent; return mLastMotionEvent; Loading Loading @@ -236,12 +260,13 @@ public class FalsingDataProvider { return; return; } } if (mRecentMotionEvents.isEmpty()) { List<MotionEvent> recentMotionEvents = getRecentMotionEvents(); if (recentMotionEvents.isEmpty()) { mFirstRecentMotionEvent = null; mFirstRecentMotionEvent = null; mLastMotionEvent = null; mLastMotionEvent = null; } else { } else { mFirstRecentMotionEvent = mRecentMotionEvents.get(0); mFirstRecentMotionEvent = recentMotionEvents.get(0); mLastMotionEvent = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1); mLastMotionEvent = recentMotionEvents.get(recentMotionEvents.size() - 1); } } calculateAngleInternal(); calculateAngleInternal(); Loading @@ -249,6 +274,17 @@ public class FalsingDataProvider { mDirty = false; 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() { private void calculateAngleInternal() { if (mRecentMotionEvents.size() < 2) { if (mRecentMotionEvents.size() < 2) { mAngle = Float.MAX_VALUE; mAngle = Float.MAX_VALUE; Loading packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -183,7 +183,7 @@ public class TimeLimitedMotionEventBuffer implements List<MotionEvent> { @Override @Override public List<MotionEvent> subList(int fromIndex, int toIndex) { public List<MotionEvent> subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException(); return mMotionEvents.subList(fromIndex, toIndex); } } class Iter implements ListIterator<MotionEvent> { class Iter implements ListIterator<MotionEvent> { Loading packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java +3 −1 Original line number Original line Diff line number Diff line Loading @@ -94,7 +94,9 @@ public class DistanceClassifierTest extends ClassifierTest { mClassifier.onTouchEvent(appendMoveEvent(1, 16, 3)); mClassifier.onTouchEvent(appendMoveEvent(1, 16, 3)); mClassifier.onTouchEvent(appendMoveEvent(1, 17, 300)); mClassifier.onTouchEvent(appendMoveEvent(1, 17, 300)); mClassifier.onTouchEvent(appendMoveEvent(1, 18, 301)); 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(); assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue(); } } Loading packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java +26 −3 Original line number Original line Diff line number Diff line Loading @@ -75,16 +75,17 @@ public class FalsingDataProviderTest extends ClassifierTest { } } @Test @Test public void test_trackMotionEvents() { public void test_trackMotionEvents_dropUpEvent() { mDataProvider.onMotionEvent(appendDownEvent(2, 9)); mDataProvider.onMotionEvent(appendDownEvent(2, 9)); mDataProvider.onMotionEvent(appendMoveEvent(4, 7)); 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(); List<MotionEvent> motionEventList = mDataProvider.getRecentMotionEvents(); assertThat(motionEventList.size()).isEqualTo(3); assertThat(motionEventList.size()).isEqualTo(3); assertThat(motionEventList.get(0).getActionMasked()).isEqualTo(MotionEvent.ACTION_DOWN); assertThat(motionEventList.get(0).getActionMasked()).isEqualTo(MotionEvent.ACTION_DOWN); assertThat(motionEventList.get(1).getActionMasked()).isEqualTo(MotionEvent.ACTION_MOVE); 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(0).getEventTime()).isEqualTo(1L); assertThat(motionEventList.get(1).getEventTime()).isEqualTo(2L); assertThat(motionEventList.get(1).getEventTime()).isEqualTo(2L); assertThat(motionEventList.get(2).getEventTime()).isEqualTo(3L); assertThat(motionEventList.get(2).getEventTime()).isEqualTo(3L); Loading @@ -96,6 +97,28 @@ public class FalsingDataProviderTest extends ClassifierTest { assertThat(motionEventList.get(2).getY()).isEqualTo(5f); 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 @Test public void test_trackRecentMotionEvents() { public void test_trackRecentMotionEvents() { mDataProvider.onMotionEvent(appendDownEvent(2, 9, 1)); mDataProvider.onMotionEvent(appendDownEvent(2, 9, 1)); Loading packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -67,6 +67,15 @@ public class ZigZagClassifierTest extends ClassifierTest { assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse(); 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 @Test public void testPass_fewTouchesHorizontal() { public void testPass_fewTouchesHorizontal() { assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse(); assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse(); Loading Loading
packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java +41 −5 Original line number Original line Diff line number Diff line Loading @@ -38,6 +38,7 @@ import javax.inject.Inject; public class FalsingDataProvider { public class FalsingDataProvider { private static final long MOTION_EVENT_AGE_MS = 1000; 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 static final float THREE_HUNDRED_SIXTY_DEG = (float) (2 * Math.PI); private final int mWidthPixels; private final int mWidthPixels; Loading @@ -60,6 +61,7 @@ public class FalsingDataProvider { private float mAngle = 0; private float mAngle = 0; private MotionEvent mFirstRecentMotionEvent; private MotionEvent mFirstRecentMotionEvent; private MotionEvent mLastMotionEvent; private MotionEvent mLastMotionEvent; private boolean mDropLastEvent; private boolean mJustUnlockedWithFace; private boolean mJustUnlockedWithFace; private boolean mA11YAction; private boolean mA11YAction; Loading Loading @@ -95,6 +97,12 @@ public class FalsingDataProvider { // Ensure prior gesture was completed. May be a no-op. // Ensure prior gesture was completed. May be a no-op. completePriorGesture(); 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); mRecentMotionEvents.addAll(motionEvents); FalsingClassifier.logVerbose("Size: " + mRecentMotionEvents.size()); FalsingClassifier.logVerbose("Size: " + mRecentMotionEvents.size()); Loading Loading @@ -129,6 +137,7 @@ public class FalsingDataProvider { mPriorMotionEvents = mRecentMotionEvents; mPriorMotionEvents = mRecentMotionEvents; mRecentMotionEvents = new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS); mRecentMotionEvents = new TimeLimitedMotionEventBuffer(MOTION_EVENT_AGE_MS); } } mDropLastEvent = false; mA11YAction = false; mA11YAction = false; } } Loading @@ -150,8 +159,18 @@ public class FalsingDataProvider { return mYdpi; 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() { public List<MotionEvent> getRecentMotionEvents() { if (!mDropLastEvent || mRecentMotionEvents.isEmpty()) { return mRecentMotionEvents; return mRecentMotionEvents; } else { return mRecentMotionEvents.subList(0, mRecentMotionEvents.size() - 1); } } } public List<MotionEvent> getPriorMotionEvents() { public List<MotionEvent> getPriorMotionEvents() { Loading @@ -169,7 +188,12 @@ public class FalsingDataProvider { return mFirstRecentMotionEvent; 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() { public MotionEvent getLastMotionEvent() { recalculateData(); recalculateData(); return mLastMotionEvent; return mLastMotionEvent; Loading Loading @@ -236,12 +260,13 @@ public class FalsingDataProvider { return; return; } } if (mRecentMotionEvents.isEmpty()) { List<MotionEvent> recentMotionEvents = getRecentMotionEvents(); if (recentMotionEvents.isEmpty()) { mFirstRecentMotionEvent = null; mFirstRecentMotionEvent = null; mLastMotionEvent = null; mLastMotionEvent = null; } else { } else { mFirstRecentMotionEvent = mRecentMotionEvents.get(0); mFirstRecentMotionEvent = recentMotionEvents.get(0); mLastMotionEvent = mRecentMotionEvents.get(mRecentMotionEvents.size() - 1); mLastMotionEvent = recentMotionEvents.get(recentMotionEvents.size() - 1); } } calculateAngleInternal(); calculateAngleInternal(); Loading @@ -249,6 +274,17 @@ public class FalsingDataProvider { mDirty = false; 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() { private void calculateAngleInternal() { if (mRecentMotionEvents.size() < 2) { if (mRecentMotionEvents.size() < 2) { mAngle = Float.MAX_VALUE; mAngle = Float.MAX_VALUE; Loading
packages/SystemUI/src/com/android/systemui/classifier/TimeLimitedMotionEventBuffer.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -183,7 +183,7 @@ public class TimeLimitedMotionEventBuffer implements List<MotionEvent> { @Override @Override public List<MotionEvent> subList(int fromIndex, int toIndex) { public List<MotionEvent> subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException(); return mMotionEvents.subList(fromIndex, toIndex); } } class Iter implements ListIterator<MotionEvent> { class Iter implements ListIterator<MotionEvent> { Loading
packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java +3 −1 Original line number Original line Diff line number Diff line Loading @@ -94,7 +94,9 @@ public class DistanceClassifierTest extends ClassifierTest { mClassifier.onTouchEvent(appendMoveEvent(1, 16, 3)); mClassifier.onTouchEvent(appendMoveEvent(1, 16, 3)); mClassifier.onTouchEvent(appendMoveEvent(1, 17, 300)); mClassifier.onTouchEvent(appendMoveEvent(1, 17, 300)); mClassifier.onTouchEvent(appendMoveEvent(1, 18, 301)); 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(); assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue(); } } Loading
packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java +26 −3 Original line number Original line Diff line number Diff line Loading @@ -75,16 +75,17 @@ public class FalsingDataProviderTest extends ClassifierTest { } } @Test @Test public void test_trackMotionEvents() { public void test_trackMotionEvents_dropUpEvent() { mDataProvider.onMotionEvent(appendDownEvent(2, 9)); mDataProvider.onMotionEvent(appendDownEvent(2, 9)); mDataProvider.onMotionEvent(appendMoveEvent(4, 7)); 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(); List<MotionEvent> motionEventList = mDataProvider.getRecentMotionEvents(); assertThat(motionEventList.size()).isEqualTo(3); assertThat(motionEventList.size()).isEqualTo(3); assertThat(motionEventList.get(0).getActionMasked()).isEqualTo(MotionEvent.ACTION_DOWN); assertThat(motionEventList.get(0).getActionMasked()).isEqualTo(MotionEvent.ACTION_DOWN); assertThat(motionEventList.get(1).getActionMasked()).isEqualTo(MotionEvent.ACTION_MOVE); 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(0).getEventTime()).isEqualTo(1L); assertThat(motionEventList.get(1).getEventTime()).isEqualTo(2L); assertThat(motionEventList.get(1).getEventTime()).isEqualTo(2L); assertThat(motionEventList.get(2).getEventTime()).isEqualTo(3L); assertThat(motionEventList.get(2).getEventTime()).isEqualTo(3L); Loading @@ -96,6 +97,28 @@ public class FalsingDataProviderTest extends ClassifierTest { assertThat(motionEventList.get(2).getY()).isEqualTo(5f); 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 @Test public void test_trackRecentMotionEvents() { public void test_trackRecentMotionEvents() { mDataProvider.onMotionEvent(appendDownEvent(2, 9, 1)); mDataProvider.onMotionEvent(appendDownEvent(2, 9, 1)); Loading
packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -67,6 +67,15 @@ public class ZigZagClassifierTest extends ClassifierTest { assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse(); 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 @Test public void testPass_fewTouchesHorizontal() { public void testPass_fewTouchesHorizontal() { assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse(); assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse(); Loading