Loading packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java +1 −1 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ public class KeyguardPatternViewController // Treat single-sized patterns as erroneous taps. if (pattern.size() == 1) { mFalsingCollector.updateFalseConfidence(FalsingClassifier.Result.falsed( 0.7, "empty pattern input")); 0.7, getClass().getSimpleName(), "empty pattern input")); } mLockPatternView.enableInput(); onPatternChecked(userId, false, 0, false /* not valid - too short */); Loading packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +45 −50 Original line number Diff line number Diff line Loading @@ -42,7 +42,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Queue; import java.util.Set; import java.util.StringJoiner; Loading Loading @@ -94,9 +93,17 @@ public class BrightLineFalsingManager implements FalsingManager { } }; private final BeliefListener mBeliefListener = belief -> { private final BeliefListener mBeliefListener = new BeliefListener() { @Override public void onBeliefChanged(double belief) { logInfo(String.format( "{belief=%s confidence=%s}", mHistoryTracker.falseBelief(), mHistoryTracker.falseConfidence())); if (belief > FALSE_BELIEF_THRESHOLD) { mFalsingBeliefListeners.forEach(FalsingBeliefListener::onFalse); logInfo("Triggering False Event (Threshold: " + FALSE_BELIEF_THRESHOLD + ")"); } } }; Loading @@ -105,13 +112,23 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public void onGestureComplete(long completionTimeMs) { if (mPriorResults != null) { mPriorResults.forEach(result -> { if (result.isFalse()) { String reason = result.getReason(); if (reason != null) { logInfo(reason); } } }); mHistoryTracker.addResults(mPriorResults, completionTimeMs); mPriorResults = null; } else { // Gestures that were not classified get treated as a false. mHistoryTracker.addResults( Collections.singleton( FalsingClassifier.Result.falsed(.8, "unclassified")), FalsingClassifier.Result.falsed( .8, getClass().getSimpleName(), "unclassified")), completionTimeMs); } } Loading Loading @@ -154,30 +171,13 @@ public class BrightLineFalsingManager implements FalsingManager { boolean result; mDataProvider.setInteractionType(interactionType); if (!mTestHarness && !mDataProvider.isJustUnlockedWithFace() && !mDockManager.isDocked()) { Stream<FalsingClassifier.Result> results = mClassifiers.stream().map(falsingClassifier -> { FalsingClassifier.Result classifierResult = mClassifiers.stream().map(falsingClassifier -> falsingClassifier.classifyGesture( interactionType, mHistoryTracker.falseBelief(), mHistoryTracker.falseConfidence()); if (classifierResult.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s, interactionType=%d}", falsingClassifier.getClass().getName(), mDataProvider.getInteractionType())); String reason = classifierResult.getReason(); if (reason != null) { logInfo(reason); } } else { logDebug(falsingClassifier.getClass().getName() + ": false"); } return classifierResult; }); mHistoryTracker.falseConfidence())); mPriorResults = new ArrayList<>(); final boolean[] localResult = {false}; results.forEach(classifierResult -> { Loading @@ -190,13 +190,13 @@ public class BrightLineFalsingManager implements FalsingManager { mPriorResults = Collections.singleton(FalsingClassifier.Result.passed(1)); } logDebug("Is false touch? " + result); logDebug("False Gesture: " + result); if (Build.IS_ENG || Build.IS_USERDEBUG) { // Copy motion events, as the passed in list gets emptied out elsewhere in the code. RECENT_SWIPES.add(new DebugSwipeRecord( result, mDataProvider.getInteractionType(), interactionType, mDataProvider.getRecentMotionEvents().stream().map( motionEvent -> new XYDt( (int) motionEvent.getX(), Loading @@ -220,37 +220,36 @@ public class BrightLineFalsingManager implements FalsingManager { FalsingClassifier.Result singleTapResult = mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents()); mPriorResults = Collections.singleton(singleTapResult); if (singleTapResult.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s}", mSingleTapClassifier.getClass().getName())); String reason = singleTapResult.getReason(); if (reason != null) { logInfo(reason); } return true; } if (robustCheck) { if (!singleTapResult.isFalse() && robustCheck) { if (mDataProvider.isJustUnlockedWithFace()) { // Immediately pass if a face is detected. mPriorResults = Collections.singleton(FalsingClassifier.Result.passed(1)); logDebug("False Single Tap: false (face detected)"); return false; } else if (!isFalseDoubleTap()) { // We must check double tapping before other heuristics. This is because // the double tap will fail if there's only been one tap. We don't want that // failure to be recorded in mPriorResults. logDebug("False Single Tap: false (double tapped)"); return false; } else if (mHistoryTracker.falseBelief() > TAP_CONFIDENCE_THRESHOLD) { mPriorResults = Collections.singleton( FalsingClassifier.Result.falsed(0, "bad history")); FalsingClassifier.Result.falsed( 0, getClass().getSimpleName(), "bad history")); logDebug("False Single Tap: true (bad history)"); return true; } else { mPriorResults = Collections.singleton(FalsingClassifier.Result.passed(0.1)); logDebug("False Single Tap: false (default)"); return false; } } else { logDebug("False Single Tap: " + singleTapResult.isFalse() + " (simple)"); return singleTapResult.isFalse(); } return false; } @Override Loading @@ -259,16 +258,12 @@ public class BrightLineFalsingManager implements FalsingManager { return false; } FalsingClassifier.Result result = mDoubleTapClassifier.classifyGesture(); FalsingClassifier.Result result = mDoubleTapClassifier.classifyGesture( Classifier.GENERIC, mHistoryTracker.falseBelief(), mHistoryTracker.falseConfidence()); mPriorResults = Collections.singleton(result); if (result.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s}", mDoubleTapClassifier.getClass().getName())); String reason = result.getReason(); if (reason != null) { logInfo(reason); } } logDebug("False Double Tap: " + result.isFalse()); return result.isFalse(); } Loading packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java +5 −4 Original line number Diff line number Diff line Loading @@ -62,15 +62,16 @@ class DiagonalClassifier extends FalsingClassifier { VERTICAL_ANGLE_RANGE); } Result calculateFalsingResult(double historyBelief, double historyConfidence) { Result calculateFalsingResult( @Classifier.InteractionType int interactionType, double historyBelief, double historyConfidence) { float angle = getAngle(); if (angle == Float.MAX_VALUE) { // Unknown angle return Result.passed(0); } if (getInteractionType() == LEFT_AFFORDANCE || getInteractionType() == RIGHT_AFFORDANCE) { if (interactionType == LEFT_AFFORDANCE || interactionType == RIGHT_AFFORDANCE) { return Result.passed(0); } Loading @@ -86,7 +87,7 @@ class DiagonalClassifier extends FalsingClassifier { || angleBetween(angle, minAngle - NINETY_DEG, maxAngle - NINETY_DEG) || angleBetween(angle, minAngle + ONE_HUNDRED_EIGHTY_DEG, maxAngle + ONE_HUNDRED_EIGHTY_DEG); return falsed ? Result.falsed(0.5f, getReason()) : Result.passed(0.5); return falsed ? falsed(0.5f, getReason()) : Result.passed(0.5); } private String getReason() { Loading packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java +5 −6 Original line number Diff line number Diff line Loading @@ -136,8 +136,6 @@ class DistanceClassifier extends FalsingClassifier { float dX = getLastMotionEvent().getX() - getFirstMotionEvent().getX(); float dY = getLastMotionEvent().getY() - getFirstMotionEvent().getY(); logInfo("dX: " + dX + " dY: " + dY + " xV: " + vX + " yV: " + vY); return new DistanceVectors(dX, dY, vX, vY); } Loading @@ -147,9 +145,10 @@ class DistanceClassifier extends FalsingClassifier { } @Override Result calculateFalsingResult(double historyBelief, double historyConfidence) { return !getPassedFlingThreshold() ? Result.falsed(0.5, getReason()) : Result.passed(0.5); Result calculateFalsingResult( @Classifier.InteractionType int interactionType, double historyBelief, double historyConfidence) { return !getPassedFlingThreshold() ? falsed(0.5, getReason()) : Result.passed(0.5); } String getReason() { Loading @@ -172,7 +171,7 @@ class DistanceClassifier extends FalsingClassifier { Result isLongSwipe() { boolean longSwipe = getPassedDistanceThreshold(); logDebug("Is longSwipe? " + longSwipe); return longSwipe ? Result.passed(0.5) : Result.falsed(0.5, getReason()); return longSwipe ? Result.passed(0.5) : falsed(0.5, getReason()); } private boolean getPassedDistanceThreshold() { Loading packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java +5 −3 Original line number Diff line number Diff line Loading @@ -46,18 +46,20 @@ public class DoubleTapClassifier extends FalsingClassifier { } @Override Result calculateFalsingResult(double historyBelief, double historyConfidence) { Result calculateFalsingResult( @Classifier.InteractionType int interactionType, double historyBelief, double historyConfidence) { List<MotionEvent> secondTapEvents = getRecentMotionEvents(); List<MotionEvent> firstTapEvents = getPriorMotionEvents(); StringBuilder reason = new StringBuilder(); if (firstTapEvents == null) { return Result.falsed(0, "Only one gesture recorded"); return falsed(0, "Only one gesture recorded"); } return !isDoubleTap(firstTapEvents, secondTapEvents, reason) ? Result.falsed(0.5, reason.toString()) : Result.passed(0.5); ? 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. */ Loading Loading
packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java +1 −1 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ public class KeyguardPatternViewController // Treat single-sized patterns as erroneous taps. if (pattern.size() == 1) { mFalsingCollector.updateFalseConfidence(FalsingClassifier.Result.falsed( 0.7, "empty pattern input")); 0.7, getClass().getSimpleName(), "empty pattern input")); } mLockPatternView.enableInput(); onPatternChecked(userId, false, 0, false /* not valid - too short */); Loading
packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +45 −50 Original line number Diff line number Diff line Loading @@ -42,7 +42,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Queue; import java.util.Set; import java.util.StringJoiner; Loading Loading @@ -94,9 +93,17 @@ public class BrightLineFalsingManager implements FalsingManager { } }; private final BeliefListener mBeliefListener = belief -> { private final BeliefListener mBeliefListener = new BeliefListener() { @Override public void onBeliefChanged(double belief) { logInfo(String.format( "{belief=%s confidence=%s}", mHistoryTracker.falseBelief(), mHistoryTracker.falseConfidence())); if (belief > FALSE_BELIEF_THRESHOLD) { mFalsingBeliefListeners.forEach(FalsingBeliefListener::onFalse); logInfo("Triggering False Event (Threshold: " + FALSE_BELIEF_THRESHOLD + ")"); } } }; Loading @@ -105,13 +112,23 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public void onGestureComplete(long completionTimeMs) { if (mPriorResults != null) { mPriorResults.forEach(result -> { if (result.isFalse()) { String reason = result.getReason(); if (reason != null) { logInfo(reason); } } }); mHistoryTracker.addResults(mPriorResults, completionTimeMs); mPriorResults = null; } else { // Gestures that were not classified get treated as a false. mHistoryTracker.addResults( Collections.singleton( FalsingClassifier.Result.falsed(.8, "unclassified")), FalsingClassifier.Result.falsed( .8, getClass().getSimpleName(), "unclassified")), completionTimeMs); } } Loading Loading @@ -154,30 +171,13 @@ public class BrightLineFalsingManager implements FalsingManager { boolean result; mDataProvider.setInteractionType(interactionType); if (!mTestHarness && !mDataProvider.isJustUnlockedWithFace() && !mDockManager.isDocked()) { Stream<FalsingClassifier.Result> results = mClassifiers.stream().map(falsingClassifier -> { FalsingClassifier.Result classifierResult = mClassifiers.stream().map(falsingClassifier -> falsingClassifier.classifyGesture( interactionType, mHistoryTracker.falseBelief(), mHistoryTracker.falseConfidence()); if (classifierResult.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s, interactionType=%d}", falsingClassifier.getClass().getName(), mDataProvider.getInteractionType())); String reason = classifierResult.getReason(); if (reason != null) { logInfo(reason); } } else { logDebug(falsingClassifier.getClass().getName() + ": false"); } return classifierResult; }); mHistoryTracker.falseConfidence())); mPriorResults = new ArrayList<>(); final boolean[] localResult = {false}; results.forEach(classifierResult -> { Loading @@ -190,13 +190,13 @@ public class BrightLineFalsingManager implements FalsingManager { mPriorResults = Collections.singleton(FalsingClassifier.Result.passed(1)); } logDebug("Is false touch? " + result); logDebug("False Gesture: " + result); if (Build.IS_ENG || Build.IS_USERDEBUG) { // Copy motion events, as the passed in list gets emptied out elsewhere in the code. RECENT_SWIPES.add(new DebugSwipeRecord( result, mDataProvider.getInteractionType(), interactionType, mDataProvider.getRecentMotionEvents().stream().map( motionEvent -> new XYDt( (int) motionEvent.getX(), Loading @@ -220,37 +220,36 @@ public class BrightLineFalsingManager implements FalsingManager { FalsingClassifier.Result singleTapResult = mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents()); mPriorResults = Collections.singleton(singleTapResult); if (singleTapResult.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s}", mSingleTapClassifier.getClass().getName())); String reason = singleTapResult.getReason(); if (reason != null) { logInfo(reason); } return true; } if (robustCheck) { if (!singleTapResult.isFalse() && robustCheck) { if (mDataProvider.isJustUnlockedWithFace()) { // Immediately pass if a face is detected. mPriorResults = Collections.singleton(FalsingClassifier.Result.passed(1)); logDebug("False Single Tap: false (face detected)"); return false; } else if (!isFalseDoubleTap()) { // We must check double tapping before other heuristics. This is because // the double tap will fail if there's only been one tap. We don't want that // failure to be recorded in mPriorResults. logDebug("False Single Tap: false (double tapped)"); return false; } else if (mHistoryTracker.falseBelief() > TAP_CONFIDENCE_THRESHOLD) { mPriorResults = Collections.singleton( FalsingClassifier.Result.falsed(0, "bad history")); FalsingClassifier.Result.falsed( 0, getClass().getSimpleName(), "bad history")); logDebug("False Single Tap: true (bad history)"); return true; } else { mPriorResults = Collections.singleton(FalsingClassifier.Result.passed(0.1)); logDebug("False Single Tap: false (default)"); return false; } } else { logDebug("False Single Tap: " + singleTapResult.isFalse() + " (simple)"); return singleTapResult.isFalse(); } return false; } @Override Loading @@ -259,16 +258,12 @@ public class BrightLineFalsingManager implements FalsingManager { return false; } FalsingClassifier.Result result = mDoubleTapClassifier.classifyGesture(); FalsingClassifier.Result result = mDoubleTapClassifier.classifyGesture( Classifier.GENERIC, mHistoryTracker.falseBelief(), mHistoryTracker.falseConfidence()); mPriorResults = Collections.singleton(result); if (result.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s}", mDoubleTapClassifier.getClass().getName())); String reason = result.getReason(); if (reason != null) { logInfo(reason); } } logDebug("False Double Tap: " + result.isFalse()); return result.isFalse(); } Loading
packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java +5 −4 Original line number Diff line number Diff line Loading @@ -62,15 +62,16 @@ class DiagonalClassifier extends FalsingClassifier { VERTICAL_ANGLE_RANGE); } Result calculateFalsingResult(double historyBelief, double historyConfidence) { Result calculateFalsingResult( @Classifier.InteractionType int interactionType, double historyBelief, double historyConfidence) { float angle = getAngle(); if (angle == Float.MAX_VALUE) { // Unknown angle return Result.passed(0); } if (getInteractionType() == LEFT_AFFORDANCE || getInteractionType() == RIGHT_AFFORDANCE) { if (interactionType == LEFT_AFFORDANCE || interactionType == RIGHT_AFFORDANCE) { return Result.passed(0); } Loading @@ -86,7 +87,7 @@ class DiagonalClassifier extends FalsingClassifier { || angleBetween(angle, minAngle - NINETY_DEG, maxAngle - NINETY_DEG) || angleBetween(angle, minAngle + ONE_HUNDRED_EIGHTY_DEG, maxAngle + ONE_HUNDRED_EIGHTY_DEG); return falsed ? Result.falsed(0.5f, getReason()) : Result.passed(0.5); return falsed ? falsed(0.5f, getReason()) : Result.passed(0.5); } private String getReason() { Loading
packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java +5 −6 Original line number Diff line number Diff line Loading @@ -136,8 +136,6 @@ class DistanceClassifier extends FalsingClassifier { float dX = getLastMotionEvent().getX() - getFirstMotionEvent().getX(); float dY = getLastMotionEvent().getY() - getFirstMotionEvent().getY(); logInfo("dX: " + dX + " dY: " + dY + " xV: " + vX + " yV: " + vY); return new DistanceVectors(dX, dY, vX, vY); } Loading @@ -147,9 +145,10 @@ class DistanceClassifier extends FalsingClassifier { } @Override Result calculateFalsingResult(double historyBelief, double historyConfidence) { return !getPassedFlingThreshold() ? Result.falsed(0.5, getReason()) : Result.passed(0.5); Result calculateFalsingResult( @Classifier.InteractionType int interactionType, double historyBelief, double historyConfidence) { return !getPassedFlingThreshold() ? falsed(0.5, getReason()) : Result.passed(0.5); } String getReason() { Loading @@ -172,7 +171,7 @@ class DistanceClassifier extends FalsingClassifier { Result isLongSwipe() { boolean longSwipe = getPassedDistanceThreshold(); logDebug("Is longSwipe? " + longSwipe); return longSwipe ? Result.passed(0.5) : Result.falsed(0.5, getReason()); return longSwipe ? Result.passed(0.5) : falsed(0.5, getReason()); } private boolean getPassedDistanceThreshold() { Loading
packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java +5 −3 Original line number Diff line number Diff line Loading @@ -46,18 +46,20 @@ public class DoubleTapClassifier extends FalsingClassifier { } @Override Result calculateFalsingResult(double historyBelief, double historyConfidence) { Result calculateFalsingResult( @Classifier.InteractionType int interactionType, double historyBelief, double historyConfidence) { List<MotionEvent> secondTapEvents = getRecentMotionEvents(); List<MotionEvent> firstTapEvents = getPriorMotionEvents(); StringBuilder reason = new StringBuilder(); if (firstTapEvents == null) { return Result.falsed(0, "Only one gesture recorded"); return falsed(0, "Only one gesture recorded"); } return !isDoubleTap(firstTapEvents, secondTapEvents, reason) ? Result.falsed(0.5, reason.toString()) : Result.passed(0.5); ? 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. */ Loading