From 1179f84f540e021126770f91f735dcb3276ec777 Mon Sep 17 00:00:00 2001 From: Dave Mankoff Date: Mon, 30 Nov 2020 11:19:32 -0500 Subject: [PATCH] Make FalsingClassifiers less stateful. Clasifiers now return a Result object on all their classification methods. The Result object now contains the "reason" for falsing instead of asking the Classifier for the reason after the fact. Bug: 172655679 Test: atest SystemUITests Change-Id: I0865f18cbae9367c203936fbbc3923de55c81007 --- .../classifier/BrightLineFalsingManager.java | 22 ++++---- .../classifier/DiagonalClassifier.java | 12 ++--- .../classifier/DistanceClassifier.java | 8 +-- .../classifier/DoubleTapClassifier.java | 25 ++++----- .../classifier/FalsingClassifier.java | 53 +++++++++++++++---- .../classifier/PointerCountClassifier.java | 15 +++--- .../classifier/ProximityClassifier.java | 15 +++--- .../classifier/SingleTapClassifier.java | 22 +++----- .../systemui/classifier/TypeClassifier.java | 24 ++++++--- .../systemui/classifier/ZigZagClassifier.java | 8 +-- .../classifier/BrightLineClassifierTest.java | 26 ++++----- .../classifier/DoubleTapClassifierTest.java | 19 ++++--- .../classifier/HistoryTrackerTest.java | 5 +- .../classifier/ProximityClassifierTest.java | 8 ++- .../classifier/SingleTapClassifierTest.java | 4 +- 15 files changed, 156 insertions(+), 110 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java index e9b1abcd5999c..e78057f5bd71a 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java @@ -137,22 +137,22 @@ public class BrightLineFalsingManager implements FalsingManager { mPreviousResult = !mTestHarness && !mDataProvider.isJustUnlockedWithFace() && !mDockManager.isDocked() && mClassifiers.stream().anyMatch(falsingClassifier -> { - boolean result = falsingClassifier.classifyGesture( + FalsingClassifier.Result result = falsingClassifier.classifyGesture( mHistoryTracker.falsePenalty(), mHistoryTracker.falseConfidence()); - if (result) { + if (result.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s, interactionType=%d}", falsingClassifier.getClass().getName(), mDataProvider.getInteractionType())); - String reason = falsingClassifier.getReason(); + String reason = result.getReason(); if (reason != null) { logInfo(reason); } } else { logDebug(falsingClassifier.getClass().getName() + ": false"); } - return result; + return result.isFalse(); }); logDebug("Is false touch? " + mPreviousResult); @@ -178,10 +178,12 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public boolean isFalseTap(boolean robustCheck) { - if (!mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents())) { + FalsingClassifier.Result singleTapResult = + mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents()); + if (singleTapResult.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s}", mSingleTapClassifier.getClass().getName())); - String reason = mSingleTapClassifier.getReason(); + String reason = singleTapResult.getReason(); if (reason != null) { logInfo(reason); } @@ -198,16 +200,16 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public boolean isFalseDoubleTap() { - boolean result = mDoubleTapClassifier.classifyGesture().isFalse(); - if (result) { + FalsingClassifier.Result result = mDoubleTapClassifier.classifyGesture(); + if (result.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s}", mDoubleTapClassifier.getClass().getName())); - String reason = mDoubleTapClassifier.getReason(); + String reason = result.getReason(); if (reason != null) { logInfo(reason); } } - return result; + return result.isFalse(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java index 3a758ae0bbf55..bbb937176f595 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java @@ -66,12 +66,12 @@ class DiagonalClassifier extends FalsingClassifier { float angle = getAngle(); if (angle == Float.MAX_VALUE) { // Unknown angle - return new Result(false, 0); + return Result.passed(0); } if (getInteractionType() == LEFT_AFFORDANCE || getInteractionType() == RIGHT_AFFORDANCE) { - return new Result(false, 0); + return Result.passed(0); } float minAngle = DIAGONAL - mHorizontalAngleRange; @@ -81,15 +81,15 @@ class DiagonalClassifier extends FalsingClassifier { maxAngle = DIAGONAL + mVerticalAngleRange; } - return new Result(angleBetween(angle, minAngle, maxAngle) + boolean falsed = angleBetween(angle, minAngle, maxAngle) || angleBetween(angle, minAngle + NINETY_DEG, maxAngle + NINETY_DEG) || angleBetween(angle, minAngle - NINETY_DEG, maxAngle - NINETY_DEG) || angleBetween(angle, minAngle + ONE_HUNDRED_EIGHTY_DEG, - maxAngle + ONE_HUNDRED_EIGHTY_DEG), 0.5f); + maxAngle + ONE_HUNDRED_EIGHTY_DEG); + return falsed ? Result.falsed(0.5f, getReason()) : Result.passed(0.5); } - @Override - String getReason() { + private String getReason() { return String.format( (Locale) null, "{angle=%f, vertical=%s}", diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java index 9661b57b620f1..4cb5aa2cce377 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java @@ -148,10 +148,10 @@ class DistanceClassifier extends FalsingClassifier { @Override Result calculateFalsingResult(double historyPenalty, double historyConfidence) { - return new Result(!getPassedFlingThreshold(), 0.5); + return !getPassedFlingThreshold() + ? Result.falsed(0.5, getReason()) : Result.passed(0.5); } - @Override String getReason() { DistanceVectors distanceVectors = getDistances(); @@ -169,10 +169,10 @@ class DistanceClassifier extends FalsingClassifier { mVerticalSwipeThresholdPx); } - boolean isLongSwipe() { + Result isLongSwipe() { boolean longSwipe = getPassedDistanceThreshold(); logDebug("Is longSwipe? " + longSwipe); - return longSwipe; + return longSwipe ? Result.passed(0.5) : Result.falsed(0.5, getReason()); } private boolean getPassedDistanceThreshold() { diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java index 225e066d1b363..64576a97ddb22 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java @@ -36,8 +36,6 @@ public class DoubleTapClassifier extends FalsingClassifier { private final float mDoubleTapSlop; private final long mDoubleTapTimeMs; - private StringBuilder mReason = new StringBuilder(); - @Inject DoubleTapClassifier(FalsingDataProvider dataProvider, SingleTapClassifier singleTapClassifier, @Named(DOUBLE_TAP_TOUCH_SLOP) float doubleTapSlop, @@ -54,27 +52,29 @@ public class DoubleTapClassifier extends FalsingClassifier { Queue> historicalEvents = getHistoricalEvents(); List firstTapEvents = historicalEvents.peek(); - mReason = new StringBuilder(); + StringBuilder reason = new StringBuilder(); if (firstTapEvents == null) { - mReason.append("Only one gesture recorded"); - return new Result(true, 1); + return Result.falsed(1, "Only one gesture recorded"); } - return new Result(!isDoubleTap(firstTapEvents, secondTapEvents, mReason), 0.5); + return !isDoubleTap(firstTapEvents, secondTapEvents, reason) + ? Result.falsed(0.5, reason.toString()) : Result.passed(0.5); } /** Returns true if the two supplied lists of {@link MotionEvent}s look like a double-tap. */ public boolean isDoubleTap(List firstEvents, List secondEvents, StringBuilder reason) { - if (!mSingleTapClassifier.isTap(firstEvents)) { - reason.append("First gesture is not a tap. ").append(mSingleTapClassifier.getReason()); + Result firstTap = mSingleTapClassifier.isTap(firstEvents); + if (firstTap.isFalse()) { + reason.append("First gesture is not a tap. ").append(firstTap.getReason()); return false; } - if (!mSingleTapClassifier.isTap(secondEvents)) { - reason.append("Second gesture is not a tap. ").append(mSingleTapClassifier.getReason()); + Result secondTap = mSingleTapClassifier.isTap(secondEvents); + if (secondTap.isFalse()) { + reason.append("Second gesture is not a tap. ").append(secondTap.getReason()); return false; } @@ -106,9 +106,4 @@ public class DoubleTapClassifier extends FalsingClassifier { return true; } - - @Override - String getReason() { - return mReason.toString(); - } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java index ce5f21a3a5c42..dbfeacfa91c46 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java @@ -120,25 +120,32 @@ public abstract class FalsingClassifier { void onSessionEnded() {}; /** - * Returns true if the data captured so far looks like a false touch. + * Returns whether a gesture looks like a false touch. + * + * See also {@link #classifyGesture(double, double)}. */ Result classifyGesture() { return calculateFalsingResult(0, 0); } - boolean classifyGesture(double historyPenalty, double historyConfidence) { - return calculateFalsingResult(historyPenalty, historyConfidence).isFalse(); + /** + * Returns whether a gesture looks like a false touch, with the option to consider history. + * + * Unlike the parameter-less version of this method, this method allows the classifier to take + * history into account, penalizing or boosting confidence in a gesture based on recent results. + * + * See also {@link #classifyGesture()}. + */ + Result classifyGesture(double historyPenalty, double historyConfidence) { + return calculateFalsingResult(historyPenalty, historyConfidence); } - abstract Result calculateFalsingResult(double historyPenalty, double historyConfidence); - /** - * Give the classifier a chance to log more details about why it triggered. + * Calculate a result based on available data. * - * This should only be called after a call to {@link #classifyGesture()}, and only if - * {@link #classifyGesture()} returns true; + * When passed a historyConfidence of 0, the history penalty should be wholly ignored. */ - abstract String getReason(); + abstract Result calculateFalsingResult(double historyPenalty, double historyConfidence); /** */ public static void logDebug(String msg) { @@ -155,13 +162,21 @@ public abstract class FalsingClassifier { BrightLineFalsingManager.logError(msg); } + /** + * A Falsing result that encapsulates the boolean result along with confidence and a reason. + */ static class Result { private final boolean mFalsed; private final double mConfidence; + private final String mReason; - Result(boolean falsed, double confidence) { + /** + * See {@link #falsed(double, String)} abd {@link #passed(double)}. + */ + private Result(boolean falsed, double confidence, String reason) { mFalsed = falsed; mConfidence = confidence; + mReason = reason; } public boolean isFalse() { @@ -171,5 +186,23 @@ public abstract class FalsingClassifier { public double getConfidence() { return mConfidence; } + + public String getReason() { + return mReason; + } + + /** + * Construct a "falsed" result indicating that a gesture should be treated as accidental. + */ + static Result falsed(double confidence, String reason) { + return new Result(true, confidence, reason); + } + + /** + * Construct a "passed" result indicating that a gesture should be allowed. + */ + static Result passed(double confidence) { + return new Result(false, confidence, null); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java index 6d8bb42bd01b8..cd399fe15de18 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java @@ -58,18 +58,19 @@ class PointerCountClassifier extends FalsingClassifier { @Override Result calculateFalsingResult(double historyPenalty, double historyConfidence) { int interactionType = getInteractionType(); - if (interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN) { - return new Result(mMaxPointerCount > MAX_ALLOWED_POINTERS_SWIPE_DOWN, 1); - } - return new Result(mMaxPointerCount > MAX_ALLOWED_POINTERS, 1); + int allowedPointerCount = + (interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN) + ? MAX_ALLOWED_POINTERS_SWIPE_DOWN : MAX_ALLOWED_POINTERS; + + return mMaxPointerCount > allowedPointerCount + ? Result.falsed(1, getReason(allowedPointerCount)) : Result.passed(0); } - @Override - String getReason() { + private String getReason(int allowedPointerCount) { return String.format( (Locale) null, "{pointersObserved=%d, threshold=%d}", mMaxPointerCount, - MAX_ALLOWED_POINTERS); + allowedPointerCount); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java index 64601362454e6..9ee85986c53cb 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java @@ -33,7 +33,7 @@ import javax.inject.Inject; /** * False touch if proximity sensor is covered for more than a certain percentage of the gesture. * - * This classifer is essentially a no-op for QUICK_SETTINGS, as we assume the sensor may be + * This classifier is essentially a no-op for QUICK_SETTINGS, as we assume the sensor may be * covered when swiping from the top. */ class ProximityClassifier extends FalsingClassifier { @@ -114,26 +114,27 @@ class ProximityClassifier extends FalsingClassifier { @Override Result calculateFalsingResult(double historyPenalty, double historyConfidence) { if (getInteractionType() == QUICK_SETTINGS) { - return new Result(false, 0); + return Result.passed(0); } logInfo("Percent of gesture in proximity: " + mPercentNear); if (mPercentNear > mPercentCoveredThreshold) { - return new Result(!mDistanceClassifier.isLongSwipe(), 0.5); + Result longSwipeResult = mDistanceClassifier.isLongSwipe(); + return longSwipeResult.isFalse() + ? Result.falsed(0.5, getReason(longSwipeResult)) : Result.passed(0.5); } - return new Result(false, 0.5); + return Result.passed(0.5); } - @Override - String getReason() { + private String getReason(Result longSwipeResult) { return String.format( (Locale) null, "{percentInProximity=%f, threshold=%f, distanceClassifier=%s}", mPercentNear, mPercentCoveredThreshold, - mDistanceClassifier.getReason()); + longSwipeResult.getReason()); } /** diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java index bcca599817401..f2622ec4e6e97 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java @@ -30,7 +30,6 @@ import javax.inject.Named; */ public class SingleTapClassifier extends FalsingClassifier { private final float mTouchSlop; - private String mReason; @Inject SingleTapClassifier(FalsingDataProvider dataProvider, @@ -41,35 +40,30 @@ public class SingleTapClassifier extends FalsingClassifier { @Override Result calculateFalsingResult(double historyPenalty, double historyConfidence) { - return new Result(!isTap(getRecentMotionEvents()), 0.5); + return isTap(getRecentMotionEvents()); } /** Given a list of {@link android.view.MotionEvent}'s, returns true if the look like a tap. */ - public boolean isTap(List motionEvents) { + public Result isTap(List motionEvents) { float downX = motionEvents.get(0).getX(); float downY = motionEvents.get(0).getY(); for (MotionEvent event : motionEvents) { + String reason; if (Math.abs(event.getX() - downX) >= mTouchSlop) { - mReason = "dX too big for a tap: " + reason = "dX too big for a tap: " + Math.abs(event.getX() - downX) + "vs " + mTouchSlop; - return false; + return Result.falsed(0.5, reason); } else if (Math.abs(event.getY() - downY) >= mTouchSlop) { - mReason = "dY too big for a tap: " + reason = "dY too big for a tap: " + Math.abs(event.getY() - downY) + "vs " + mTouchSlop; - return false; + return Result.falsed(0.5, reason); } } - mReason = ""; - return true; - } - - @Override - String getReason() { - return mReason; + 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 3269d836859e5..d470d62971706 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java @@ -43,27 +43,35 @@ public class TypeClassifier extends FalsingClassifier { boolean up = isUp(); boolean right = isRight(); + boolean wrongDirection = true; switch (getInteractionType()) { case QUICK_SETTINGS: case PULSE_EXPAND: case NOTIFICATION_DRAG_DOWN: - return new Result(!vertical || up, 0.5); + wrongDirection = !vertical || up; + break; case NOTIFICATION_DISMISS: - return new Result(vertical, 0.5); + wrongDirection = vertical; + break; case UNLOCK: case BOUNCER_UNLOCK: - return new Result(!vertical || !up, 0.5); + wrongDirection = !vertical || !up; + break; case LEFT_AFFORDANCE: // Swiping from the bottom left corner for camera or similar. - return new Result(!right || !up, 0.5); + wrongDirection = !right || !up; + break; case RIGHT_AFFORDANCE: // Swiping from the bottom right corner for camera or similar. - return new Result(right || !up, 0.5); + wrongDirection = right || !up; + break; default: - return new Result(true, 1); + wrongDirection = true; + break; } + + return wrongDirection ? Result.falsed(1, getReason()) : Result.passed(0.5); } - @Override - String getReason() { + private String getReason() { return String.format("{vertical=%s, up=%s, right=%s}", isVertical(), isUp(), isRight()); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java index 04634da47ac9c..2bfb2186191b5 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java @@ -95,7 +95,7 @@ class ZigZagClassifier extends FalsingClassifier { // For vertical lines, the difference in the y direction should be small. if (motionEvents.size() < 3) { - return new Result(false, 0); + return Result.passed(0); } List rotatedPoints; @@ -155,11 +155,11 @@ class ZigZagClassifier extends FalsingClassifier { logDebug("Straightness Deviance: (" + devianceX + "," + devianceY + ") vs " + "(" + maxXDeviance + "," + maxYDeviance + ")"); - return new Result(devianceX > maxXDeviance || devianceY > maxYDeviance, 0.5); + return devianceX > maxXDeviance || devianceY > maxYDeviance + ? Result.falsed(0.5, getReason()) : Result.passed(0.5); } - @Override - String getReason() { + private String getReason() { return String.format( (Locale) null, "{devianceX=%f, maxDevianceX=%s, devianceY=%s, maxDevianceY=%s}", diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java index d9df8282f0865..8c547b127da20 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java @@ -72,12 +72,14 @@ public class BrightLineClassifierTest extends SysuiTestCase { private HistoryTracker mHistoryTracker; private FakeSystemClock mSystemClock = new FakeSystemClock(); - private FalsingClassifier.Result mTrueResult = new FalsingClassifier.Result(true, 1); - private FalsingClassifier.Result mFalseResult = new FalsingClassifier.Result(false, 1); + private final FalsingClassifier.Result mFalsedResult = FalsingClassifier.Result.falsed(1, ""); + private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1); @Before public void setup() { MockitoAnnotations.initMocks(this); + when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult); + when(mClassifierB.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult); mClassifiers.add(mClassifierA); mClassifiers.add(mClassifierB); when(mFalsingDataProvider.isDirty()).thenReturn(true); @@ -111,20 +113,20 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Test public void testIsFalseTouch_ClassifierARejects() { - when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(true); + when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mFalsedResult); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isTrue(); } @Test public void testIsFalseTouch_ClassifierBRejects() { - when(mClassifierB.classifyGesture(anyDouble(), anyDouble())).thenReturn(true); + when(mClassifierB.classifyGesture(anyDouble(), anyDouble())).thenReturn(mFalsedResult); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isTrue(); } @Test public void testIsFalseTouch_FaceAuth() { // Even when the classifiers report a false, we should allow. - when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(true); + when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult); when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse(); @@ -133,7 +135,7 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Test public void testIsFalseTouch_Docked() { // Even when the classifiers report a false, we should allow. - when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(true); + when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult); mDockManager.setIsDocked(true); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse(); @@ -141,36 +143,36 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Test public void testIsFalseTap_BasicCheck() { - when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(false); + when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mFalsedResult); assertThat(mBrightLineFalsingManager.isFalseTap(false)).isTrue(); - when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(true); + when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult); assertThat(mBrightLineFalsingManager.isFalseTap(false)).isFalse(); } @Test public void testIsFalseTap_RobustCheck_NoFaceAuth() { - when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(true); + when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult); mFalsingDataProvider.setJustUnlockedWithFace(false); assertThat(mBrightLineFalsingManager.isFalseTap(true)).isTrue(); } @Test public void testIsFalseTap_RobustCheck_FaceAuth() { - when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(true); + when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult); when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true); assertThat(mBrightLineFalsingManager.isFalseTap(true)).isFalse(); } @Test public void testIsFalseDoubleTap() { - when(mDoubleTapClassifier.classifyGesture()).thenReturn(mFalseResult); + when(mDoubleTapClassifier.classifyGesture()).thenReturn(mPassedResult); assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isFalse(); - when(mDoubleTapClassifier.classifyGesture()).thenReturn(mTrueResult); + when(mDoubleTapClassifier.classifyGesture()).thenReturn(mFalsedResult); assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isTrue(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java index 67890a5573673..17c2700c5bdac 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java @@ -55,6 +55,9 @@ public class DoubleTapClassifierTest extends ClassifierTest { private SingleTapClassifier mSingleTapClassifier; private DoubleTapClassifier mClassifier; + private final FalsingClassifier.Result mFalsedResult = FalsingClassifier.Result.falsed(1, ""); + private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1); + @Before public void setup() { super.setup(); @@ -77,7 +80,7 @@ public class DoubleTapClassifierTest extends ClassifierTest { @Test public void testSingleTap() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1); @@ -87,7 +90,7 @@ public class DoubleTapClassifierTest extends ClassifierTest { @Test public void testDoubleTap() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mPassedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -97,13 +100,13 @@ public class DoubleTapClassifierTest extends ClassifierTest { addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, TOUCH_SLOP, TOUCH_SLOP); addMotionEvent(2, 3, MotionEvent.ACTION_UP, TOUCH_SLOP, TOUCH_SLOP); - boolean result = mClassifier.classifyGesture().isFalse(); - assertThat(mClassifier.getReason(), result, is(false)); + FalsingClassifier.Result result = mClassifier.classifyGesture(); + assertThat(result.getReason(), result.isFalse(), is(false)); } @Test public void testBadFirstTap() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(false, true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mPassedResult, mFalsedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -119,7 +122,7 @@ public class DoubleTapClassifierTest extends ClassifierTest { @Test public void testBadSecondTap() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true, false); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult, mPassedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -135,7 +138,7 @@ public class DoubleTapClassifierTest extends ClassifierTest { @Test public void testBadTouchSlop() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -151,7 +154,7 @@ public class DoubleTapClassifierTest extends ClassifierTest { @Test public void testBadTouchSlow() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java index 8e7cc4e1013cb..01cce3579b0cb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java @@ -120,6 +120,9 @@ public class HistoryTrackerTest extends SysuiTestCase { private void addResult(boolean falsed, double confidence) { mHistoryTracker.addResults(Collections.singletonList( - new FalsingClassifier.Result(falsed, confidence)), mSystemClock.uptimeMillis()); + falsed + ? FalsingClassifier.Result.falsed(confidence, "test") + : FalsingClassifier.Result.passed(confidence)), + mSystemClock.uptimeMillis()); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java index 3986bb7ff7eb1..ba8ca9abc2d7f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java @@ -50,12 +50,16 @@ public class ProximityClassifierTest extends ClassifierTest { private DistanceClassifier mDistanceClassifier; private FalsingClassifier mClassifier; + private final FalsingClassifier.Result mFalsedResult = + FalsingClassifier.Result.falsed(1, "test"); + private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1); + @Before public void setup() { super.setup(); MockitoAnnotations.initMocks(this); when(mDataProvider.getInteractionType()).thenReturn(GENERIC); - when(mDistanceClassifier.isLongSwipe()).thenReturn(false); + when(mDistanceClassifier.isLongSwipe()).thenReturn(mFalsedResult); mClassifier = new ProximityClassifier( mDistanceClassifier, mDataProvider, new DeviceConfigProxyFake()); } @@ -117,7 +121,7 @@ public class ProximityClassifierTest extends ClassifierTest { mClassifier.onProximityEvent(createSensorEvent(true, 1)); mClassifier.onProximityEvent(createSensorEvent(false, 11)); touchUp(10); - when(mDistanceClassifier.isLongSwipe()).thenReturn(true); + when(mDistanceClassifier.isLongSwipe()).thenReturn(mPassedResult); assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java index e4470759cb46f..62c876f99a159 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java @@ -142,12 +142,12 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); - assertThat(mClassifier.isTap(mMotionEvents), is(true)); + assertThat(mClassifier.isTap(mMotionEvents).isFalse(), is(false)); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP + 1); - assertThat(mClassifier.isTap(mMotionEvents), is(false)); + assertThat(mClassifier.isTap(mMotionEvents).isFalse(), is(true)); }