From d33284a22ddaaef9a5f674ec2b3169d42effb5fb Mon Sep 17 00:00:00 2001 From: Dave Mankoff Date: Thu, 15 Sep 2022 22:05:08 +0000 Subject: [PATCH] Analyze vertical swipes on QS's Scroll View. When media controls are shown, the full qs+media controls often takes up more than one full screen. Swiping up on this causes the qs to vertically scroll instead of collapse. Prior to this cl, we weren't analyzing such swipes in the FalsingManager. Now we do. No explicit action is taken in the event of a false swipe. It simply gives us more signal. Enough bad swipes may implicitly cause the lock screen to reset itself. Fixes: 241708312 Test: manual Change-Id: I5adfb3a22b2f0f51efb87d56a6cfc5459cd67006 --- .../classifier/BrightLineFalsingManager.java | 8 ++- .../systemui/classifier/Classifier.java | 6 +- .../classifier/DistanceClassifier.java | 4 +- .../classifier/FalsingClassifier.java | 5 ++ .../classifier/FalsingDataProvider.java | 6 +- .../classifier/ProximityClassifier.java | 4 +- .../systemui/classifier/TypeClassifier.java | 8 ++- .../systemui/classifier/ZigZagClassifier.java | 4 +- .../qs/NonInterceptingScrollView.java | 13 +++- .../android/systemui/qs/QSContainerImpl.java | 4 ++ .../qs/QSContainerImplController.java | 33 +++++++++- .../systemui/qs/QSPanelController.java | 4 +- .../classifier/DistanceClassifierTest.java | 6 +- .../classifier/TypeClassifierTest.java | 65 +++++++++++++++---- 14 files changed, 137 insertions(+), 33 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java index bfbf37a5d3e95..d53e56f7b852d 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java @@ -220,7 +220,7 @@ public class BrightLineFalsingManager implements FalsingManager { return r; }).collect(Collectors.toList()); - logDebug("False Gesture: " + localResult[0]); + logDebug("False Gesture (type: " + interactionType + "): " + localResult[0]); return localResult[0]; } @@ -454,6 +454,12 @@ public class BrightLineFalsingManager implements FalsingManager { } } + static void logVerbose(String msg) { + if (DEBUG) { + Log.v(TAG, msg); + } + } + static void logInfo(String msg) { Log.i(TAG, msg); RECENT_INFO_LOG.add(msg); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java index f18413be0134d..c2922968b58ec 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java @@ -42,8 +42,9 @@ public abstract class Classifier { public static final int QS_COLLAPSE = 12; public static final int UDFPS_AUTHENTICATION = 13; public static final int LOCK_ICON = 14; - public static final int QS_SWIPE = 15; + public static final int QS_SWIPE_SIDE = 15; public static final int BACK_GESTURE = 16; + public static final int QS_SWIPE_NESTED = 17; @IntDef({ QUICK_SETTINGS, @@ -62,7 +63,8 @@ public abstract class Classifier { BRIGHTNESS_SLIDER, UDFPS_AUTHENTICATION, LOCK_ICON, - QS_SWIPE, + QS_SWIPE_SIDE, + QS_SWIPE_NESTED, BACK_GESTURE }) @Retention(RetentionPolicy.SOURCE) diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java index d0fe1c37d4fab..5e4f149d3ca38 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java @@ -24,6 +24,7 @@ import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHT import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_THRESHOLD_IN; import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER; import static com.android.systemui.classifier.Classifier.QS_COLLAPSE; +import static com.android.systemui.classifier.Classifier.QS_SWIPE_NESTED; import static com.android.systemui.classifier.Classifier.SHADE_DRAG; import android.provider.DeviceConfig; @@ -156,7 +157,8 @@ class DistanceClassifier extends FalsingClassifier { || interactionType == QS_COLLAPSE || interactionType == Classifier.UDFPS_AUTHENTICATION || interactionType == Classifier.LOCK_ICON - || interactionType == Classifier.QS_SWIPE) { + || interactionType == Classifier.QS_SWIPE_SIDE + || interactionType == QS_SWIPE_NESTED) { return Result.passed(0); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java index d75752841023a..d18d62f025fe1 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java @@ -147,6 +147,11 @@ public abstract class FalsingClassifier { BrightLineFalsingManager.logDebug(msg); } + /** */ + public static void logVerbose(String msg) { + BrightLineFalsingManager.logVerbose(msg); + } + /** */ public static void logInfo(String msg) { BrightLineFalsingManager.logInfo(msg); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java index a3ecb0c0b273b..3991a35e958ae 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java @@ -78,10 +78,10 @@ public class FalsingDataProvider { void onMotionEvent(MotionEvent motionEvent) { List motionEvents = unpackMotionEvent(motionEvent); - FalsingClassifier.logDebug("Unpacked into: " + motionEvents.size()); + FalsingClassifier.logVerbose("Unpacked into: " + motionEvents.size()); if (BrightLineFalsingManager.DEBUG) { for (MotionEvent m : motionEvents) { - FalsingClassifier.logDebug( + FalsingClassifier.logVerbose( "x,y,t: " + m.getX() + "," + m.getY() + "," + m.getEventTime()); } } @@ -92,7 +92,7 @@ public class FalsingDataProvider { } mRecentMotionEvents.addAll(motionEvents); - FalsingClassifier.logDebug("Size: " + mRecentMotionEvents.size()); + FalsingClassifier.logVerbose("Size: " + mRecentMotionEvents.size()); mMotionEventListeners.forEach(listener -> listener.onMotionEvent(motionEvent)); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java index 32d9ca59951da..07f94e792a934 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java @@ -19,7 +19,7 @@ package com.android.systemui.classifier; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD; import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER; import static com.android.systemui.classifier.Classifier.QS_COLLAPSE; -import static com.android.systemui.classifier.Classifier.QS_SWIPE; +import static com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE; import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; import android.provider.DeviceConfig; @@ -119,7 +119,7 @@ class ProximityClassifier extends FalsingClassifier { @Classifier.InteractionType int interactionType, double historyBelief, double historyConfidence) { if (interactionType == QUICK_SETTINGS || interactionType == BRIGHTNESS_SLIDER - || interactionType == QS_COLLAPSE || interactionType == QS_SWIPE) { + || interactionType == QS_COLLAPSE || interactionType == QS_SWIPE_SIDE) { return Result.passed(0); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java index f040712706cd8..776bc88ad6bfc 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java @@ -24,7 +24,8 @@ import static com.android.systemui.classifier.Classifier.NOTIFICATION_DISMISS; import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN; import static com.android.systemui.classifier.Classifier.PULSE_EXPAND; import static com.android.systemui.classifier.Classifier.QS_COLLAPSE; -import static com.android.systemui.classifier.Classifier.QS_SWIPE; +import static com.android.systemui.classifier.Classifier.QS_SWIPE_NESTED; +import static com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE; import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; import static com.android.systemui.classifier.Classifier.RIGHT_AFFORDANCE; import static com.android.systemui.classifier.Classifier.SHADE_DRAG; @@ -86,9 +87,12 @@ public class TypeClassifier extends FalsingClassifier { case QS_COLLAPSE: wrongDirection = !vertical || !up; break; - case QS_SWIPE: + case QS_SWIPE_SIDE: wrongDirection = vertical; break; + case QS_SWIPE_NESTED: + wrongDirection = !vertical; + break; default: wrongDirection = true; break; diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java index 40c28fab51b82..de2bdf7ded755 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java @@ -137,8 +137,8 @@ class ZigZagClassifier extends FalsingClassifier { runningAbsDy += Math.abs(point.y - pY); pX = point.x; pY = point.y; - logDebug("(x, y, runningAbsDx, runningAbsDy) - (" + pX + ", " + pY + ", " + runningAbsDx - + ", " + runningAbsDy + ")"); + logVerbose("(x, y, runningAbsDx, runningAbsDy) - (" + + pX + ", " + pY + ", " + runningAbsDx + ", " + runningAbsDy + ")"); } float devianceX = runningAbsDx - actualDx; diff --git a/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java b/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java index cd3609108c283..1d058744ac942 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java @@ -28,21 +28,29 @@ import android.widget.ScrollView; public class NonInterceptingScrollView extends ScrollView { private final int mTouchSlop; + private float mDownY; private boolean mScrollEnabled = true; + private boolean mPreventingIntercept; public NonInterceptingScrollView(Context context, AttributeSet attrs) { super(context, attrs); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); } + public boolean isPreventingIntercept() { + return mPreventingIntercept; + } + @Override public boolean onTouchEvent(MotionEvent ev) { int action = ev.getActionMasked(); switch (action) { case MotionEvent.ACTION_DOWN: + mPreventingIntercept = false; if (canScrollVertically(1)) { // If we can scroll down, make sure we're not intercepted by the parent + mPreventingIntercept = true; final ViewParent parent = getParent(); if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); @@ -62,10 +70,13 @@ public class NonInterceptingScrollView extends ScrollView { public boolean onInterceptTouchEvent(MotionEvent ev) { // If there's a touch on this view and we can scroll down, we don't want to be intercepted int action = ev.getActionMasked(); + switch (action) { case MotionEvent.ACTION_DOWN: - // If we can scroll down, make sure non of our parents intercepts us. + mPreventingIntercept = false; + // If we can scroll down, make sure none of our parents intercepts us. if (canScrollVertically(1)) { + mPreventingIntercept = true; final ViewParent parent = getParent(); if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java index 7b1ddd62ec6e9..ef87fb49752db 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java @@ -131,6 +131,10 @@ public class QSContainerImpl extends FrameLayout implements Dumpable { updateClippingPath(); } + public NonInterceptingScrollView getQSPanelContainer() { + return mQSPanelContainer; + } + public void disable(int state1, int state2, boolean animate) { final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0; if (disabled == mQsDisabled) return; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java index 7d61991c910a6..dea7bb5abd710 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java @@ -16,8 +16,13 @@ package com.android.systemui.qs; -import android.content.res.Configuration; +import static com.android.systemui.classifier.Classifier.QS_SWIPE_NESTED; +import android.content.res.Configuration; +import android.view.MotionEvent; +import android.view.View; + +import com.android.systemui.plugins.FalsingManager; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.util.ViewController; @@ -30,6 +35,8 @@ public class QSContainerImplController extends ViewController { private final QSPanelController mQsPanelController; private final QuickStatusBarHeaderController mQuickStatusBarHeaderController; private final ConfigurationController mConfigurationController; + private final FalsingManager mFalsingManager; + private final NonInterceptingScrollView mQSPanelContainer; private final ConfigurationController.ConfigurationListener mConfigurationListener = new ConfigurationController.ConfigurationListener() { @@ -39,14 +46,32 @@ public class QSContainerImplController extends ViewController { } }; + private final View.OnTouchListener mContainerTouchHandler = new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + if (event.getActionMasked() == MotionEvent.ACTION_UP) { + if (mQSPanelContainer.isPreventingIntercept()) { + // There's really no action here to take, but we need to tell the FalsingManager + mFalsingManager.isFalseTouch(QS_SWIPE_NESTED); + } + } + return false; + } + }; + @Inject - QSContainerImplController(QSContainerImpl view, QSPanelController qsPanelController, + QSContainerImplController( + QSContainerImpl view, + QSPanelController qsPanelController, QuickStatusBarHeaderController quickStatusBarHeaderController, - ConfigurationController configurationController) { + ConfigurationController configurationController, + FalsingManager falsingManager) { super(view); mQsPanelController = qsPanelController; mQuickStatusBarHeaderController = quickStatusBarHeaderController; mConfigurationController = configurationController; + mFalsingManager = falsingManager; + mQSPanelContainer = mView.getQSPanelContainer(); } @Override @@ -62,11 +87,13 @@ public class QSContainerImplController extends ViewController { protected void onViewAttached() { mView.updateResources(mQsPanelController, mQuickStatusBarHeaderController); mConfigurationController.addCallback(mConfigurationListener); + mQSPanelContainer.setOnTouchListener(mContainerTouchHandler); } @Override protected void onViewDetached() { mConfigurationController.removeCallback(mConfigurationListener); + mQSPanelContainer.setOnTouchListener(null); } public QSContainerImpl getView() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java index 59b871cc41bb8..205d565839671 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java @@ -16,7 +16,7 @@ package com.android.systemui.qs; -import static com.android.systemui.classifier.Classifier.QS_SWIPE; +import static com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE; import static com.android.systemui.media.dagger.MediaModule.QS_PANEL; import static com.android.systemui.qs.QSPanel.QS_SHOW_BRIGHTNESS; import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER; @@ -76,7 +76,7 @@ public class QSPanelController extends QSPanelControllerBase { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getActionMasked() == MotionEvent.ACTION_UP) { - mFalsingManager.isFalseTouch(QS_SWIPE); + mFalsingManager.isFalseTouch(QS_SWIPE_SIDE); } return false; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java index 8e00d10a7d396..faa5db4327a68 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java @@ -17,7 +17,7 @@ package com.android.systemui.classifier; import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER; -import static com.android.systemui.classifier.Classifier.QS_SWIPE; +import static com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE; import static com.google.common.truth.Truth.assertThat; @@ -106,9 +106,9 @@ public class DistanceClassifierTest extends ClassifierTest { } @Test - public void testPass_QsSwipeAlwaysPasses() { + public void testPass_QsSwipeSideAlwaysPasses() { mClassifier.onTouchEvent(appendDownEvent(1, 1)); - assertThat(mClassifier.classifyGesture(QS_SWIPE, 0.5, 1).isFalse()) + assertThat(mClassifier.classifyGesture(QS_SWIPE_SIDE, 0.5, 1).isFalse()) .isFalse(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java index 1d61e29cad351..d70d6fc6baa62 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java @@ -22,7 +22,8 @@ import static com.android.systemui.classifier.Classifier.LEFT_AFFORDANCE; import static com.android.systemui.classifier.Classifier.NOTIFICATION_DISMISS; import static com.android.systemui.classifier.Classifier.NOTIFICATION_DRAG_DOWN; import static com.android.systemui.classifier.Classifier.PULSE_EXPAND; -import static com.android.systemui.classifier.Classifier.QS_SWIPE; +import static com.android.systemui.classifier.Classifier.QS_SWIPE_NESTED; +import static com.android.systemui.classifier.Classifier.QS_SWIPE_SIDE; import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS; import static com.android.systemui.classifier.Classifier.RIGHT_AFFORDANCE; import static com.android.systemui.classifier.Classifier.UNLOCK; @@ -323,44 +324,86 @@ public class TypeClassifierTest extends ClassifierTest { } @Test - public void testPass_QsSwipe() { + public void testPass_QsSwipeSide() { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); // up and right should cause no effect. when(mDataProvider.isRight()).thenReturn(false); - assertThat(mClassifier.classifyGesture(QS_SWIPE, 0.5, 0).isFalse()).isFalse(); + assertThat(mClassifier.classifyGesture(QS_SWIPE_SIDE, 0.5, 0).isFalse()).isFalse(); when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(false); - assertThat(mClassifier.classifyGesture(QS_SWIPE, 0.5, 0).isFalse()).isFalse(); + assertThat(mClassifier.classifyGesture(QS_SWIPE_SIDE, 0.5, 0).isFalse()).isFalse(); when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.classifyGesture(QS_SWIPE, 0.5, 0).isFalse()).isFalse(); + assertThat(mClassifier.classifyGesture(QS_SWIPE_SIDE, 0.5, 0).isFalse()).isFalse(); when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.classifyGesture(QS_SWIPE, 0.5, 0).isFalse()).isFalse(); + assertThat(mClassifier.classifyGesture(QS_SWIPE_SIDE, 0.5, 0).isFalse()).isFalse(); } @Test - public void testFalse_QsSwipe() { + public void testFalse_QsSwipeSide() { when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(false); // up and right should cause no effect. when(mDataProvider.isRight()).thenReturn(false); - assertThat(mClassifier.classifyGesture(QS_SWIPE, 0.5, 0).isFalse()).isTrue(); + assertThat(mClassifier.classifyGesture(QS_SWIPE_SIDE, 0.5, 0).isFalse()).isTrue(); when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(false); - assertThat(mClassifier.classifyGesture(QS_SWIPE, 0.5, 0).isFalse()).isTrue(); + assertThat(mClassifier.classifyGesture(QS_SWIPE_SIDE, 0.5, 0).isFalse()).isTrue(); when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.classifyGesture(QS_SWIPE, 0.5, 0).isFalse()).isTrue(); + assertThat(mClassifier.classifyGesture(QS_SWIPE_SIDE, 0.5, 0).isFalse()).isTrue(); when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.classifyGesture(QS_SWIPE, 0.5, 0).isFalse()).isTrue(); + assertThat(mClassifier.classifyGesture(QS_SWIPE_SIDE, 0.5, 0).isFalse()).isTrue(); + } + + @Test + public void testPass_QsNestedSwipe() { + when(mDataProvider.isVertical()).thenReturn(true); + + when(mDataProvider.isUp()).thenReturn(false); // up and right should cause no effect. + when(mDataProvider.isRight()).thenReturn(false); + assertThat(mClassifier.classifyGesture(QS_SWIPE_NESTED, 0.5, 0).isFalse()).isFalse(); + + when(mDataProvider.isUp()).thenReturn(true); + when(mDataProvider.isRight()).thenReturn(false); + assertThat(mClassifier.classifyGesture(QS_SWIPE_NESTED, 0.5, 0).isFalse()).isFalse(); + + when(mDataProvider.isUp()).thenReturn(false); + when(mDataProvider.isRight()).thenReturn(true); + assertThat(mClassifier.classifyGesture(QS_SWIPE_NESTED, 0.5, 0).isFalse()).isFalse(); + + when(mDataProvider.isUp()).thenReturn(true); + when(mDataProvider.isRight()).thenReturn(true); + assertThat(mClassifier.classifyGesture(QS_SWIPE_NESTED, 0.5, 0).isFalse()).isFalse(); + } + + @Test + public void testFalse_QsNestedSwipe() { + when(mDataProvider.isVertical()).thenReturn(false); + + when(mDataProvider.isUp()).thenReturn(false); // up and right should cause no effect. + when(mDataProvider.isRight()).thenReturn(false); + assertThat(mClassifier.classifyGesture(QS_SWIPE_NESTED, 0.5, 0).isFalse()).isTrue(); + + when(mDataProvider.isUp()).thenReturn(true); + when(mDataProvider.isRight()).thenReturn(false); + assertThat(mClassifier.classifyGesture(QS_SWIPE_NESTED, 0.5, 0).isFalse()).isTrue(); + + when(mDataProvider.isUp()).thenReturn(false); + when(mDataProvider.isRight()).thenReturn(true); + assertThat(mClassifier.classifyGesture(QS_SWIPE_NESTED, 0.5, 0).isFalse()).isTrue(); + + when(mDataProvider.isUp()).thenReturn(true); + when(mDataProvider.isRight()).thenReturn(true); + assertThat(mClassifier.classifyGesture(QS_SWIPE_NESTED, 0.5, 0).isFalse()).isTrue(); } }