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

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

Merge "Make FalsingClassifiers less stateful."

parents 801b7580 1179f84f
Loading
Loading
Loading
Loading
+12 −10
Original line number Diff line number Diff line
@@ -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
+6 −6
Original line number Diff line number Diff line
@@ -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}",
+4 −4
Original line number Diff line number Diff line
@@ -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() {
+10 −15
Original line number Diff line number Diff line
@@ -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<? extends List<MotionEvent>> historicalEvents = getHistoricalEvents();
        List<MotionEvent> 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<MotionEvent> firstEvents, List<MotionEvent> 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();
    }
}
+43 −10
Original line number Diff line number Diff line
@@ -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);
        }
    }
}
Loading