Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0f06e106 authored by Dave Mankoff's avatar Dave Mankoff Committed by Android (Google) Code Review
Browse files

Merge "Add more logging for falsing." into sc-dev

parents 916102b2 4124a204
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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 */);
+45 −50
Original line number Diff line number Diff line
@@ -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;
@@ -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 + ")");
            }
        }
    };

@@ -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);
                    }
                }
@@ -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 -> {
@@ -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(),
@@ -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
@@ -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();
    }

+5 −4
Original line number Diff line number Diff line
@@ -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);
        }

@@ -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() {
+5 −6
Original line number Diff line number Diff line
@@ -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);
    }

@@ -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() {
@@ -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() {
+5 −3
Original line number Diff line number Diff line
@@ -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