Add HistoryTracker to FalsingManager

This institutes a HistoryTracker mechanism that will allow the
FalsingManager to take recent activity into account when classifying
gestures. The HistoryTracker returns a penalty that is pased to each
classifier for them to use when making decisions.

As of right now, no classifier actually uses the history penalty when
making a classification decision.

The HistoryTracker keeps records of the last 3 seconds of falsing
results, applying a decaying penalty to the results over time. It also
assigns a confidence to its results, based on how consistent they are.

Each individual classifier is also able to return a confidence score
now, such that, if they are not confident in their decision, they
don't throw off the score that gets stored in the HistoryTracker.
Confidences currently returned by the classifiers are somewhat
arbitrary and should be adjusted in future CLs.

Everything is currently open for adjustment:
- The length of history
- The decay function applied to history
- The method by which our confidence in the history is calculated
- The confidence returned by each individual classfier
- How the history penalty is taken into account by each classifier
- ... and probably more.

Bug: 172655679
Test: atest SystemUITests
Change-Id: Ief2a5144a0cda659c7d78ed6e489231d481b6872
This commit is contained in:
Dave Mankoff
2020-11-24 15:57:57 -05:00
parent 7898548ed6
commit 3ae5052e7b
29 changed files with 622 additions and 227 deletions

View File

@@ -60,8 +60,8 @@ public interface FalsingManager {
* Returns true if the last two gestures do not look like a double tap.
*
* Only works on data that has already been reported to the FalsingManager. Be sure that
* {@link #onTouchEvent(MotionEvent, int, int)} has already been called for all of the
* taps you want considered.
* {@link com.android.systemui.classifier.FalsingCollector#onTouchEvent(MotionEvent)}
* has already been called for all of the taps you want considered.
*
* This looks at the last two gestures on the screen, ensuring that they meet the following
* criteria:
@@ -85,8 +85,6 @@ public interface FalsingManager {
boolean isReportingEnabled();
void onTouchEvent(MotionEvent ev, int width, int height);
/** From com.android.systemui.Dumpable. */
void dump(FileDescriptor fd, PrintWriter pw, String[] args);

View File

@@ -23,7 +23,6 @@ import android.net.Uri;
import android.os.Build;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.view.MotionEvent;
import androidx.annotation.NonNull;
@@ -33,10 +32,12 @@ import com.android.systemui.dagger.qualifiers.TestHarness;
import com.android.systemui.dock.DockManager;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.util.sensors.ThresholdSensor;
import com.android.systemui.util.time.SystemClock;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
@@ -63,6 +64,8 @@ public class BrightLineFalsingManager implements FalsingManager {
private final DockManager mDockManager;
private final SingleTapClassifier mSingleTapClassifier;
private final DoubleTapClassifier mDoubleTapClassifier;
private final HistoryTracker mHistoryTracker;
private final SystemClock mSystemClock;
private final boolean mTestHarness;
private final MetricsLogger mMetricsLogger;
private int mIsFalseTouchCalls;
@@ -85,6 +88,17 @@ public class BrightLineFalsingManager implements FalsingManager {
}
};
private final FalsingDataProvider.GestureCompleteListener mGestureCompleteListener =
new FalsingDataProvider.GestureCompleteListener() {
@Override
public void onGestureComplete() {
mHistoryTracker.addResults(
mClassifiers.stream().map(FalsingClassifier::classifyGesture)
.collect(Collectors.toCollection(ArrayList::new)),
mSystemClock.uptimeMillis());
}
};
private boolean mPreviousResult = false;
@Inject
@@ -92,6 +106,7 @@ public class BrightLineFalsingManager implements FalsingManager {
DockManager dockManager, MetricsLogger metricsLogger,
@Named(BRIGHT_LINE_GESTURE_CLASSIFERS) Set<FalsingClassifier> classifiers,
SingleTapClassifier singleTapClassifier, DoubleTapClassifier doubleTapClassifier,
HistoryTracker historyTracker, SystemClock systemClock,
@TestHarness boolean testHarness) {
mDataProvider = falsingDataProvider;
mDockManager = dockManager;
@@ -99,9 +114,12 @@ public class BrightLineFalsingManager implements FalsingManager {
mClassifiers = classifiers;
mSingleTapClassifier = singleTapClassifier;
mDoubleTapClassifier = doubleTapClassifier;
mHistoryTracker = historyTracker;
mSystemClock = systemClock;
mTestHarness = testHarness;
mDataProvider.addSessionListener(mSessionListener);
mDataProvider.addGestureCompleteListener(mGestureCompleteListener);
}
@Override
@@ -119,7 +137,8 @@ public class BrightLineFalsingManager implements FalsingManager {
mPreviousResult = !mTestHarness
&& !mDataProvider.isJustUnlockedWithFace() && !mDockManager.isDocked()
&& mClassifiers.stream().anyMatch(falsingClassifier -> {
boolean result = falsingClassifier.isFalseTouch();
boolean result = falsingClassifier.classifyGesture(
mHistoryTracker.falsePenalty(), mHistoryTracker.falseConfidence());
if (result) {
logInfo(String.format(
(Locale) null,
@@ -179,7 +198,7 @@ public class BrightLineFalsingManager implements FalsingManager {
@Override
public boolean isFalseDoubleTap() {
boolean result = mDoubleTapClassifier.isFalseTouch();
boolean result = mDoubleTapClassifier.classifyGesture().isFalse();
if (result) {
logInfo(String.format(
(Locale) null, "{classifier=%s}", mDoubleTapClassifier.getClass().getName()));
@@ -191,13 +210,6 @@ public class BrightLineFalsingManager implements FalsingManager {
return result;
}
@Override
public void onTouchEvent(MotionEvent motionEvent, int width, int height) {
// TODO: some of these classifiers might allow us to abort early, meaning we don't have to
// make these calls.
mClassifiers.forEach((classifier) -> classifier.onTouchEvent(motionEvent));
}
@Override
public void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent) {
// TODO: some of these classifiers might allow us to abort early, meaning we don't have to
@@ -271,6 +283,8 @@ public class BrightLineFalsingManager implements FalsingManager {
@Override
public void cleanup() {
mDataProvider.removeSessionListener(mSessionListener);
mDataProvider.removeGestureCompleteListener(mGestureCompleteListener);
mClassifiers.forEach(FalsingClassifier::cleanup);
}
static void logDebug(String msg) {

View File

@@ -62,17 +62,16 @@ class DiagonalClassifier extends FalsingClassifier {
VERTICAL_ANGLE_RANGE);
}
@Override
boolean isFalseTouch() {
Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
float angle = getAngle();
if (angle == Float.MAX_VALUE) { // Unknown angle
return false;
return new Result(false, 0);
}
if (getInteractionType() == LEFT_AFFORDANCE
|| getInteractionType() == RIGHT_AFFORDANCE) {
return false;
return new Result(false, 0);
}
float minAngle = DIAGONAL - mHorizontalAngleRange;
@@ -82,11 +81,11 @@ class DiagonalClassifier extends FalsingClassifier {
maxAngle = DIAGONAL + mVerticalAngleRange;
}
return angleBetween(angle, minAngle, maxAngle)
return new Result(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);
maxAngle + ONE_HUNDRED_EIGHTY_DEG), 0.5f);
}
@Override

View File

@@ -123,7 +123,6 @@ class DistanceClassifier extends FalsingClassifier {
}
VelocityTracker velocityTracker = VelocityTracker.obtain();
for (MotionEvent motionEvent : motionEvents) {
velocityTracker.addMovement(motionEvent);
}
@@ -148,8 +147,8 @@ class DistanceClassifier extends FalsingClassifier {
}
@Override
public boolean isFalseTouch() {
return !getPassedFlingThreshold();
Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
return new Result(!getPassedFlingThreshold(), 0.5);
}
@Override

View File

@@ -49,7 +49,7 @@ public class DoubleTapClassifier extends FalsingClassifier {
}
@Override
boolean isFalseTouch() {
Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
List<MotionEvent> secondTapEvents = getRecentMotionEvents();
Queue<? extends List<MotionEvent>> historicalEvents = getHistoricalEvents();
List<MotionEvent> firstTapEvents = historicalEvents.peek();
@@ -58,10 +58,10 @@ public class DoubleTapClassifier extends FalsingClassifier {
if (firstTapEvents == null) {
mReason.append("Only one gesture recorded");
return true;
return new Result(true, 1);
}
return !isDoubleTap(firstTapEvents, secondTapEvents, mReason);
return new Result(!isDoubleTap(firstTapEvents, secondTapEvents, mReason), 0.5);
}
/** Returns true if the two supplied lists of {@link MotionEvent}s look like a double-tap. */

View File

@@ -29,8 +29,11 @@ import java.util.Queue;
public abstract class FalsingClassifier {
private final FalsingDataProvider mDataProvider;
private final FalsingDataProvider.MotionEventListener mMotionEventListener = this::onTouchEvent;
FalsingClassifier(FalsingDataProvider dataProvider) {
mDataProvider = dataProvider;
mDataProvider.addMotionEventListener(mMotionEventListener);
}
List<MotionEvent> getRecentMotionEvents() {
@@ -89,6 +92,10 @@ public abstract class FalsingClassifier {
return mDataProvider.getInteractionType();
}
void cleanup() {
mDataProvider.removeMotionEventListener(mMotionEventListener);
}
/**
* Called whenever a MotionEvent occurs.
*
@@ -115,13 +122,21 @@ public abstract class FalsingClassifier {
/**
* Returns true if the data captured so far looks like a false touch.
*/
abstract boolean isFalseTouch();
Result classifyGesture() {
return calculateFalsingResult(0, 0);
}
boolean classifyGesture(double historyPenalty, double historyConfidence) {
return calculateFalsingResult(historyPenalty, historyConfidence).isFalse();
}
abstract Result calculateFalsingResult(double historyPenalty, double historyConfidence);
/**
* Give the classifier a chance to log more details about why it triggered.
*
* This should only be called after a call to {@link #isFalseTouch()}, and only if
* {@link #isFalseTouch()} returns true;
* This should only be called after a call to {@link #classifyGesture()}, and only if
* {@link #classifyGesture()} returns true;
*/
abstract String getReason();
@@ -139,4 +154,22 @@ public abstract class FalsingClassifier {
public static void logError(String msg) {
BrightLineFalsingManager.logError(msg);
}
static class Result {
private final boolean mFalsed;
private final double mConfidence;
Result(boolean falsed, double confidence) {
mFalsed = falsed;
mConfidence = confidence;
}
public boolean isFalse() {
return mFalsed;
}
public double getConfidence() {
return mConfidence;
}
}
}

View File

@@ -113,7 +113,7 @@ public interface FalsingCollector {
void onBouncerHidden();
/** */
void onTouchEvent(MotionEvent ev, int width, int height);
void onTouchEvent(MotionEvent ev);
/** */
void cleanup();

View File

@@ -143,7 +143,7 @@ public class FalsingCollectorFake implements FalsingCollector {
}
@Override
public void onTouchEvent(MotionEvent ev, int width, int height) {
public void onTouchEvent(MotionEvent ev) {
}
@Override

View File

@@ -244,9 +244,8 @@ class FalsingCollectorImpl implements FalsingCollector {
}
@Override
public void onTouchEvent(MotionEvent ev, int width, int height) {
public void onTouchEvent(MotionEvent ev) {
mFalsingDataProvider.onMotionEvent(ev);
mFalsingManager.onTouchEvent(ev, width, height);
}
@Override

View File

@@ -50,6 +50,8 @@ public class FalsingDataProvider {
private final float mXdpi;
private final float mYdpi;
private final List<SessionListener> mSessionListeners = new ArrayList<>();
private final List<MotionEventListener> mMotionEventListeners = new ArrayList<>();
private final List<GestureCompleteListener> mGestuerCompleteListeners = new ArrayList<>();
private @Classifier.InteractionType int mInteractionType;
private final Deque<TimeLimitedMotionEventBuffer> mExtendedMotionEvents = new LinkedList<>();
@@ -97,6 +99,8 @@ public class FalsingDataProvider {
FalsingClassifier.logDebug("Size: " + mRecentMotionEvents.size());
mMotionEventListeners.forEach(listener -> listener.onMotionEvent(motionEvent));
mDirty = true;
}
@@ -321,6 +325,26 @@ public class FalsingDataProvider {
mSessionListeners.remove(listener);
}
/** Register a {@link MotionEventListener}. */
public void addMotionEventListener(MotionEventListener listener) {
mMotionEventListeners.add(listener);
}
/** Unegister a {@link MotionEventListener}. */
public void removeMotionEventListener(MotionEventListener listener) {
mMotionEventListeners.remove(listener);
}
/** Register a {@link GestureCompleteListener}. */
public void addGestureCompleteListener(GestureCompleteListener listener) {
mGestuerCompleteListeners.add(listener);
}
/** Unregister a {@link GestureCompleteListener}. */
public void removeGestureCompleteListener(GestureCompleteListener listener) {
mGestuerCompleteListeners.remove(listener);
}
void onSessionStarted() {
mSessionListeners.forEach(SessionListener::onSessionStarted);
}
@@ -353,4 +377,16 @@ public class FalsingDataProvider {
/** Called when the lock screen exits and falsing-tracking ends. */
void onSessionEnded();
}
/** Callback for receiving {@link android.view.MotionEvent}s as they are reported. */
public interface MotionEventListener {
/** */
void onMotionEvent(MotionEvent ev);
}
/** Callback to be alerted when the current gesture ends. */
public interface GestureCompleteListener {
/** */
void onGestureComplete();
}
}

View File

@@ -17,7 +17,6 @@
package com.android.systemui.classifier;
import android.net.Uri;
import android.view.MotionEvent;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.plugins.FalsingManager;
@@ -116,11 +115,6 @@ public class FalsingManagerFake implements FalsingManager {
return mIsReportingEnabled;
}
@Override
public void onTouchEvent(MotionEvent ev, int width, int height) {
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
}

View File

@@ -19,7 +19,6 @@ package com.android.systemui.classifier;
import android.content.Context;
import android.net.Uri;
import android.provider.DeviceConfig;
import android.view.MotionEvent;
import androidx.annotation.NonNull;
@@ -161,11 +160,6 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable {
return mInternalFalsingManager.isReportingEnabled();
}
@Override
public void onTouchEvent(MotionEvent ev, int width, int height) {
mInternalFalsingManager.onTouchEvent(ev, width, height);
}
@Override
public void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent) {
mInternalFalsingManager.onProximityEvent(proximityEvent);

View File

@@ -0,0 +1,177 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.classifier;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.util.time.SystemClock;
import java.util.Collection;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
/**
* A stateful class for tracking recent {@link FalsingManager} results.
*
* Can return a "penalty" based on recent gestures that may make it harder or easier to
* unlock a phone, as well as a "confidence" relating to how consistent recent falsing results
* have been.
*/
@SysUISingleton
public class HistoryTracker {
private static final double HISTORY_DECAY = 0.8f;
private static final long DECAY_INTERVAL_MS = 100;
// We expire items once their decay factor is below 0.001.
private static final double MINIMUM_SCORE = 0.001;
private static final long TOTAL_DECAY_TIME_MS =
DECAY_INTERVAL_MS * (long) (Math.log(MINIMUM_SCORE) / Math.log(HISTORY_DECAY));
private final SystemClock mSystemClock;
DelayQueue<CombinedResult> mResults = new DelayQueue<>();
@Inject
HistoryTracker(SystemClock systemClock) {
mSystemClock = systemClock;
}
/**
* Returns how much the HistoryClassifier thinks the past events indicate pocket dialing.
*
* A result of 0 means that all prior gestures succeeded or there is no data to
* calculate a score with. Use {@link #falseConfidence()} to differentiate between the
* two cases.
*
* A result of 1 means that all prior gestures were very obviously false. The current gesture
* might be valid, but it should have a high-bar to be classified as such.
*
* See also {@link #falseConfidence()}.
*/
double falsePenalty() {
//noinspection StatementWithEmptyBody
while (mResults.poll() != null) {
// Empty out the expired results.
}
if (mResults.isEmpty()) {
return 0;
}
long nowMs = mSystemClock.uptimeMillis();
return mResults.stream()
.map(result -> result.getDecayedScore(nowMs))
.reduce(0.0, Double::sum) / mResults.size();
}
/**
* Returns how confident the HistoryClassifier is in its own score.
*
* A result of 0.0 means that there are no data to make a calculation with. The HistoryTracker's
* results have nothing to add and should not be considered.
*
* A result of 0.5 means that the data are not consistent with each other, sometimes falsing
* sometimes not.
*
* A result of 1 means that there are ample, fresh data to act upon that is all consistent
* with each other.
*
* See als {@link #falsePenalty()}.
*/
double falseConfidence() {
//noinspection StatementWithEmptyBody
while (mResults.poll() != null) {
// Empty out the expired results.
}
// Our confidence is 1 - the population stddev. Smaller stddev == higher confidence.
if (mResults.isEmpty()) {
return 0;
}
double mean = mResults.stream()
.map(CombinedResult::getScore)
.reduce(0.0, Double::sum) / mResults.size();
double stddev = Math.sqrt(
mResults.stream()
.map(result -> Math.pow(result.getScore() - mean, 2))
.reduce(0.0, Double::sum) / mResults.size());
return 1 - stddev;
}
void addResults(Collection<FalsingClassifier.Result> results, long uptimeMillis) {
double finalScore = 0;
for (FalsingClassifier.Result result : results) {
// A confidence of 1 adds either 0 for non-falsed or 1 for falsed.
// A confidence of 0 adds 0.5.
finalScore += (result.isFalse() ? .5 : -.5) * result.getConfidence() + 0.5;
}
finalScore /= results.size();
//noinspection StatementWithEmptyBody
while (mResults.poll() != null) {
// Empty out the expired results.
}
mResults.add(new CombinedResult(uptimeMillis, finalScore));
}
/**
* Represents a falsing score combing all the classifiers together.
*
* Can "decay" over time, such that older results contribute less. Once they drop below
* a certain threshold, the {@link #getDelay(TimeUnit)} method will return <= 0, indicating
* that this result can be discarded.
*/
private class CombinedResult implements Delayed {
private final long mExpiryMs;
private final double mScore;
CombinedResult(long uptimeMillis, double score) {
mExpiryMs = uptimeMillis + TOTAL_DECAY_TIME_MS;
mScore = score;
}
double getDecayedScore(long nowMs) {
long remainingTimeMs = mExpiryMs - nowMs;
long decayedTimeMs = TOTAL_DECAY_TIME_MS - remainingTimeMs;
double timeIntervals = (double) decayedTimeMs / DECAY_INTERVAL_MS;
return mScore * Math.pow(HISTORY_DECAY, timeIntervals);
}
double getScore() {
return mScore;
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(mExpiryMs - mSystemClock.uptimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
long ourDelay = getDelay(TimeUnit.MILLISECONDS);
long otherDelay = o.getDelay(TimeUnit.MILLISECONDS);
return Long.compare(ourDelay, otherDelay);
}
}
}

View File

@@ -56,12 +56,12 @@ class PointerCountClassifier extends FalsingClassifier {
}
@Override
public boolean isFalseTouch() {
Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
int interactionType = getInteractionType();
if (interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN) {
return mMaxPointerCount > MAX_ALLOWED_POINTERS_SWIPE_DOWN;
return new Result(mMaxPointerCount > MAX_ALLOWED_POINTERS_SWIPE_DOWN, 1);
}
return mMaxPointerCount > MAX_ALLOWED_POINTERS;
return new Result(mMaxPointerCount > MAX_ALLOWED_POINTERS, 1);
}
@Override

View File

@@ -112,18 +112,18 @@ class ProximityClassifier extends FalsingClassifier {
}
@Override
public boolean isFalseTouch() {
Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
if (getInteractionType() == QUICK_SETTINGS) {
return false;
return new Result(false, 0);
}
logInfo("Percent of gesture in proximity: " + mPercentNear);
if (mPercentNear > mPercentCoveredThreshold) {
return !mDistanceClassifier.isLongSwipe();
return new Result(!mDistanceClassifier.isLongSwipe(), 0.5);
}
return false;
return new Result(false, 0.5);
}
@Override

View File

@@ -40,8 +40,8 @@ public class SingleTapClassifier extends FalsingClassifier {
}
@Override
boolean isFalseTouch() {
return !isTap(getRecentMotionEvents());
Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
return new Result(!isTap(getRecentMotionEvents()), 0.5);
}
/** Given a list of {@link android.view.MotionEvent}'s, returns true if the look like a tap. */

View File

@@ -38,7 +38,7 @@ public class TypeClassifier extends FalsingClassifier {
}
@Override
public boolean isFalseTouch() {
Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
boolean vertical = isVertical();
boolean up = isUp();
boolean right = isRight();
@@ -47,18 +47,18 @@ public class TypeClassifier extends FalsingClassifier {
case QUICK_SETTINGS:
case PULSE_EXPAND:
case NOTIFICATION_DRAG_DOWN:
return !vertical || up;
return new Result(!vertical || up, 0.5);
case NOTIFICATION_DISMISS:
return vertical;
return new Result(vertical, 0.5);
case UNLOCK:
case BOUNCER_UNLOCK:
return !vertical || !up;
return new Result(!vertical || !up, 0.5);
case LEFT_AFFORDANCE: // Swiping from the bottom left corner for camera or similar.
return !right || !up;
return new Result(!right || !up, 0.5);
case RIGHT_AFFORDANCE: // Swiping from the bottom right corner for camera or similar.
return right || !up;
return new Result(right || !up, 0.5);
default:
return true;
return new Result(true, 1);
}
}

View File

@@ -84,7 +84,7 @@ class ZigZagClassifier extends FalsingClassifier {
}
@Override
boolean isFalseTouch() {
Result calculateFalsingResult(double historyPenalty, double historyConfidence) {
List<MotionEvent> motionEvents = getRecentMotionEvents();
// Rotate horizontal gestures to be horizontal between their first and last point.
// Rotate vertical gestures to be vertical between their first and last point.
@@ -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 false;
return new Result(false, 0);
}
List<Point> rotatedPoints;
@@ -155,7 +155,7 @@ class ZigZagClassifier extends FalsingClassifier {
logDebug("Straightness Deviance: (" + devianceX + "," + devianceY + ") vs "
+ "(" + maxXDeviance + "," + maxYDeviance + ")");
return devianceX > maxXDeviance || devianceY > maxYDeviance;
return new Result(devianceX > maxXDeviance || devianceY > maxYDeviance, 0.5);
}
@Override

View File

@@ -238,7 +238,7 @@ public class NotificationShadeWindowViewController {
if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) {
return false;
}
mFalsingCollector.onTouchEvent(ev, mView.getWidth(), mView.getHeight());
mFalsingCollector.onTouchEvent(ev);
mGestureDetector.onTouchEvent(ev);
if (mBrightnessMirror != null
&& mBrightnessMirror.getVisibility() == View.VISIBLE) {

View File

@@ -20,6 +20,8 @@ import static com.android.systemui.util.mockito.KotlinMockitoHelpersKt.any;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyDouble;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -31,15 +33,19 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.testing.FakeMetricsLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingDataProvider.GestureCompleteListener;
import com.android.systemui.dock.DockManagerFake;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -62,6 +68,12 @@ public class BrightLineClassifierTest extends SysuiTestCase {
@Mock
private FalsingClassifier mClassifierB;
private final List<MotionEvent> mMotionEventList = new ArrayList<>();
@Mock
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);
@Before
public void setup() {
@@ -71,7 +83,8 @@ public class BrightLineClassifierTest extends SysuiTestCase {
when(mFalsingDataProvider.isDirty()).thenReturn(true);
when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, mDockManager,
mMetricsLogger, mClassifiers, mSingleTapClassfier, mDoubleTapClassifier, false);
mMetricsLogger, mClassifiers, mSingleTapClassfier, mDoubleTapClassifier,
mHistoryTracker, mSystemClock, false);
}
@Test
@@ -98,20 +111,20 @@ public class BrightLineClassifierTest extends SysuiTestCase {
@Test
public void testIsFalseTouch_ClassifierARejects() {
when(mClassifierA.isFalseTouch()).thenReturn(true);
when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(true);
assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isTrue();
}
@Test
public void testIsFalseTouch_ClassifierBRejects() {
when(mClassifierB.isFalseTouch()).thenReturn(true);
when(mClassifierB.classifyGesture(anyDouble(), anyDouble())).thenReturn(true);
assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isTrue();
}
@Test
public void testIsFalseTouch_FaceAuth() {
// Even when the classifiers report a false, we should allow.
when(mClassifierA.isFalseTouch()).thenReturn(true);
when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(true);
when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true);
assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse();
@@ -120,7 +133,7 @@ public class BrightLineClassifierTest extends SysuiTestCase {
@Test
public void testIsFalseTouch_Docked() {
// Even when the classifiers report a false, we should allow.
when(mClassifierA.isFalseTouch()).thenReturn(true);
when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(true);
mDockManager.setIsDocked(true);
assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse();
@@ -153,12 +166,26 @@ public class BrightLineClassifierTest extends SysuiTestCase {
@Test
public void testIsFalseDoubleTap() {
when(mDoubleTapClassifier.isFalseTouch()).thenReturn(false);
when(mDoubleTapClassifier.classifyGesture()).thenReturn(mFalseResult);
assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isFalse();
when(mDoubleTapClassifier.isFalseTouch()).thenReturn(true);
when(mDoubleTapClassifier.classifyGesture()).thenReturn(mTrueResult);
assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isTrue();
}
@Test
public void testHistory() {
ArgumentCaptor<GestureCompleteListener> gestureCompleteListenerCaptor =
ArgumentCaptor.forClass(GestureCompleteListener.class);
verify(mFalsingDataProvider).addGestureCompleteListener(
gestureCompleteListenerCaptor.capture());
GestureCompleteListener gestureCompleteListener = gestureCompleteListenerCaptor.getValue();
gestureCompleteListener.onGestureComplete();
verify(mHistoryTracker).addResults(any(Collection.class), eq(mSystemClock.uptimeMillis()));
}
}

View File

@@ -69,93 +69,93 @@ public class DiagonalClassifierTest extends ClassifierTest {
@Test
public void testPass_UnknownAngle() {
when(mDataProvider.getAngle()).thenReturn(Float.MAX_VALUE);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
public void testPass_VerticalSwipe() {
when(mDataProvider.getAngle()).thenReturn(UP_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(DOWN_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
public void testPass_MostlyVerticalSwipe() {
when(mDataProvider.getAngle()).thenReturn(UP_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(UP_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(DOWN_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(DOWN_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS * 2);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
public void testPass_BarelyVerticalSwipe() {
when(mDataProvider.getAngle()).thenReturn(
UP_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(
UP_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(
DOWN_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(
DOWN_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS * 2);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
public void testPass_HorizontalSwipe() {
when(mDataProvider.getAngle()).thenReturn(RIGHT_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(LEFT_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
public void testPass_MostlyHorizontalSwipe() {
when(mDataProvider.getAngle()).thenReturn(RIGHT_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(RIGHT_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(LEFT_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(LEFT_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
public void testPass_BarelyHorizontalSwipe() {
when(mDataProvider.getAngle()).thenReturn(
RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(
LEFT_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(
LEFT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getAngle()).thenReturn(
RIGHT_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS * 2);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -163,12 +163,12 @@ public class DiagonalClassifierTest extends ClassifierTest {
when(mDataProvider.getInteractionType()).thenReturn(LEFT_AFFORDANCE);
when(mDataProvider.getAngle()).thenReturn(
RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.getInteractionType()).thenReturn(RIGHT_AFFORDANCE);
when(mDataProvider.getAngle()).thenReturn(
LEFT_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
// This classifier may return false for other angles, but these are the only
// two that actually matter, as affordances generally only travel in these two directions.
@@ -182,37 +182,37 @@ public class DiagonalClassifierTest extends ClassifierTest {
when(mDataProvider.isVertical()).thenReturn(false);
when(mDataProvider.getAngle()).thenReturn(
RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.getAngle()).thenReturn(
UP_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.getAngle()).thenReturn(
LEFT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.getAngle()).thenReturn(
DOWN_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
// Vertical Swipes
when(mDataProvider.isVertical()).thenReturn(true);
when(mDataProvider.getAngle()).thenReturn(
RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.getAngle()).thenReturn(
UP_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.getAngle()).thenReturn(
LEFT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.getAngle()).thenReturn(
DOWN_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
}

View File

@@ -51,32 +51,32 @@ public class DistanceClassifierTest extends ClassifierTest {
@Test
public void testPass_noPointer() {
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
public void testPass_fling() {
mClassifier.onTouchEvent(appendDownEvent(1, 1));
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
mClassifier.onTouchEvent(appendMoveEvent(1, 40));
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
mClassifier.onTouchEvent(appendUpEvent(1, 80));
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
public void testFail_flingShort() {
mClassifier.onTouchEvent(appendDownEvent(1, 1));
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
mClassifier.onTouchEvent(appendMoveEvent(1, 2));
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
mClassifier.onTouchEvent(appendUpEvent(1, 10));
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -84,26 +84,26 @@ public class DistanceClassifierTest extends ClassifierTest {
// These events, in testing, result in a fling that falls just short of the threshold.
mClassifier.onTouchEvent(appendDownEvent(1, 1, 1));
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
mClassifier.onTouchEvent(appendMoveEvent(1, 15, 2));
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
mClassifier.onTouchEvent(appendMoveEvent(1, 16, 3));
mClassifier.onTouchEvent(appendMoveEvent(1, 17, 300));
mClassifier.onTouchEvent(appendMoveEvent(1, 18, 301));
mClassifier.onTouchEvent(appendUpEvent(1, 19, 501));
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
public void testPass_swipe() {
mClassifier.onTouchEvent(appendDownEvent(1, 1));
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
mClassifier.onTouchEvent(appendMoveEvent(1, mDataProvider.getYdpi() * 3, 3));
mClassifier.onTouchEvent(appendUpEvent(1, mDataProvider.getYdpi() * 3, 300));
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
}

View File

@@ -81,7 +81,7 @@ public class DoubleTapClassifierTest extends ClassifierTest {
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1);
boolean result = mClassifier.isFalseTouch();
boolean result = mClassifier.classifyGesture().isFalse();
assertThat("Single tap recognized as a valid double tap", result, is(true));
}
@@ -97,7 +97,7 @@ 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.isFalseTouch();
boolean result = mClassifier.classifyGesture().isFalse();
assertThat(mClassifier.getReason(), result, is(false));
}
@@ -113,7 +113,7 @@ public class DoubleTapClassifierTest extends ClassifierTest {
addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, 1, 1);
addMotionEvent(2, 3, MotionEvent.ACTION_UP, 1, 1);
boolean result = mClassifier.isFalseTouch();
boolean result = mClassifier.classifyGesture().isFalse();
assertThat("Bad first touch allowed", result, is(true));
}
@@ -129,7 +129,7 @@ public class DoubleTapClassifierTest extends ClassifierTest {
addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, 1, 1);
addMotionEvent(2, 3, MotionEvent.ACTION_UP, 1, 1);
boolean result = mClassifier.isFalseTouch();
boolean result = mClassifier.classifyGesture().isFalse();
assertThat("Bad second touch allowed", result, is(true));
}
@@ -145,7 +145,7 @@ public class DoubleTapClassifierTest extends ClassifierTest {
addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, TOUCH_SLOP + 1, TOUCH_SLOP);
addMotionEvent(2, 3, MotionEvent.ACTION_UP, TOUCH_SLOP, TOUCH_SLOP + 1);
boolean result = mClassifier.isFalseTouch();
boolean result = mClassifier.classifyGesture().isFalse();
assertThat("Sloppy second touch allowed", result, is(true));
}
@@ -163,7 +163,7 @@ public class DoubleTapClassifierTest extends ClassifierTest {
addMotionEvent(DOUBLE_TAP_TIMEOUT_MS + 1, DOUBLE_TAP_TIMEOUT_MS + 2,
MotionEvent.ACTION_UP, 1, 1);
boolean result = mClassifier.isFalseTouch();
boolean result = mClassifier.classifyGesture().isFalse();
assertThat("Slow second tap allowed", result, is(true));
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.classifier;
import static com.google.common.truth.Truth.assertThat;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import java.util.Collections;
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class HistoryTrackerTest extends SysuiTestCase {
private FakeSystemClock mSystemClock = new FakeSystemClock();
private HistoryTracker mHistoryTracker;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mHistoryTracker = new HistoryTracker(mSystemClock);
}
@Test
public void testNoDataNoPenalty() {
assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0);
}
@Test
public void testOneResultFullConfidence() {
addResult(true, 1);
assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
}
@Test
public void testMultipleResultsSameTimestamp() {
addResult(true, 1);
addResult(false, 1);
assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0.5);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0.5);
}
@Test
public void testMultipleConfidences() {
addResult(true, 1);
addResult(true, 0);
assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0.75);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(.75);
}
@Test
public void testDecay() {
addResult(true, 1);
assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
mSystemClock.advanceTime(1000);
assertThat(mHistoryTracker.falsePenalty()).isWithin(0.01).of(0.1);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
}
@Test
public void testMultipleResultsDifferentTimestamp() {
addResult(true, 1);
mSystemClock.advanceTime(1000);
addResult(false, .5);
assertThat(mHistoryTracker.falsePenalty()).isWithin(0.01).of(0.17);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0.625);
}
@Test
public void testCompleteDecay() {
addResult(true, 1);
assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
mSystemClock.advanceTime(2999);
assertThat(mHistoryTracker.falsePenalty()).isGreaterThan(0);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1);
mSystemClock.advanceTime(1);
assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0);
assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0);
}
private void addResult(boolean falsed, double confidence) {
mHistoryTracker.addResults(Collections.singletonList(
new FalsingClassifier.Result(falsed, confidence)), mSystemClock.uptimeMillis());
}
}

View File

@@ -50,13 +50,13 @@ public class PointerCountClassifierTest extends ClassifierTest {
@Test
public void testPass_noPointer() {
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
public void testPass_singlePointer() {
mClassifier.onTouchEvent(appendDownEvent(1, 1));
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -72,7 +72,7 @@ public class PointerCountClassifierTest extends ClassifierTest {
0, 0);
mClassifier.onTouchEvent(motionEvent);
motionEvent.recycle();
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -89,6 +89,6 @@ public class PointerCountClassifierTest extends ClassifierTest {
mClassifier.onTouchEvent(motionEvent);
motionEvent.recycle();
getDataProvider().setInteractionType(QUICK_SETTINGS);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
}

View File

@@ -69,7 +69,7 @@ public class ProximityClassifierTest extends ClassifierTest {
public void testPass_uncovered() {
touchDown();
touchUp(10);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -78,7 +78,7 @@ public class ProximityClassifierTest extends ClassifierTest {
mClassifier.onProximityEvent(createSensorEvent(true, 1));
mClassifier.onProximityEvent(createSensorEvent(false, 2));
touchUp(20);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -88,7 +88,7 @@ public class ProximityClassifierTest extends ClassifierTest {
mClassifier.onProximityEvent(createSensorEvent(true, 1));
mClassifier.onProximityEvent(createSensorEvent(false, 11));
touchUp(10);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -97,7 +97,7 @@ public class ProximityClassifierTest extends ClassifierTest {
mClassifier.onProximityEvent(createSensorEvent(true, 1));
mClassifier.onProximityEvent(createSensorEvent(false, 11));
touchUp(10);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -108,7 +108,7 @@ public class ProximityClassifierTest extends ClassifierTest {
mClassifier.onProximityEvent(createSensorEvent(true, 96));
mClassifier.onProximityEvent(createSensorEvent(false, 100));
touchUp(100);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -118,7 +118,7 @@ public class ProximityClassifierTest extends ClassifierTest {
mClassifier.onProximityEvent(createSensorEvent(false, 11));
touchUp(10);
when(mDistanceClassifier.isLongSwipe()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
private void touchDown() {

View File

@@ -70,14 +70,14 @@ public class SingleTapClassifierTest extends ClassifierTest {
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
mMotionEvents.clear();
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
addMotionEvent(0, 1, MotionEvent.ACTION_UP, -TOUCH_SLOP + 2, 1);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@@ -86,14 +86,14 @@ public class SingleTapClassifierTest extends ClassifierTest {
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
mMotionEvents.clear();
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, -TOUCH_SLOP + 2);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@@ -102,14 +102,14 @@ public class SingleTapClassifierTest extends ClassifierTest {
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP + 1, 1);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
mMotionEvents.clear();
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
addMotionEvent(0, 1, MotionEvent.ACTION_UP, -TOUCH_SLOP - 1, 1);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@@ -118,14 +118,14 @@ public class SingleTapClassifierTest extends ClassifierTest {
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP + 1);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
mMotionEvents.clear();
addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1);
addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, -TOUCH_SLOP - 1);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -134,7 +134,7 @@ public class SingleTapClassifierTest extends ClassifierTest {
addMotionEvent(0, 1, MotionEvent.ACTION_MOVE, 1, TOUCH_SLOP + 1);
addMotionEvent(0, 2, MotionEvent.ACTION_UP, 1, 1);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test

View File

@@ -61,10 +61,10 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isUp()).thenReturn(false);
when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect.
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -73,11 +73,11 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isVertical()).thenReturn(false);
when(mDataProvider.isUp()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isVertical()).thenReturn(true);
when(mDataProvider.isUp()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -87,10 +87,10 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isUp()).thenReturn(false);
when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect.
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -99,11 +99,11 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isVertical()).thenReturn(false);
when(mDataProvider.isUp()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isVertical()).thenReturn(true);
when(mDataProvider.isUp()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -113,10 +113,10 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isUp()).thenReturn(false);
when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect.
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -125,11 +125,11 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isVertical()).thenReturn(false);
when(mDataProvider.isUp()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isVertical()).thenReturn(true);
when(mDataProvider.isUp()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -139,19 +139,19 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isUp()).thenReturn(false); // up and right should cause no effect.
when(mDataProvider.isRight()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.isUp()).thenReturn(true);
when(mDataProvider.isRight()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.isUp()).thenReturn(false);
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.isUp()).thenReturn(true);
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -161,19 +161,19 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isUp()).thenReturn(false); // up and right should cause no effect.
when(mDataProvider.isRight()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isUp()).thenReturn(true);
when(mDataProvider.isRight()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isUp()).thenReturn(false);
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isUp()).thenReturn(true);
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@@ -185,10 +185,10 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect.
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -197,15 +197,15 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isVertical()).thenReturn(false);
when(mDataProvider.isUp()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isVertical()).thenReturn(true);
when(mDataProvider.isUp()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isVertical()).thenReturn(false);
when(mDataProvider.isUp()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -216,10 +216,10 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect.
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -228,15 +228,15 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isVertical()).thenReturn(false);
when(mDataProvider.isUp()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isVertical()).thenReturn(true);
when(mDataProvider.isUp()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isVertical()).thenReturn(false);
when(mDataProvider.isUp()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -247,10 +247,10 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isVertical()).thenReturn(false); // vertical should cause no effect.
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.isVertical()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -259,15 +259,15 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isRight()).thenReturn(false);
when(mDataProvider.isUp()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isRight()).thenReturn(true);
when(mDataProvider.isUp()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isRight()).thenReturn(false);
when(mDataProvider.isUp()).thenReturn(false);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -278,10 +278,10 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isVertical()).thenReturn(false); // vertical should cause no effect.
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
when(mDataProvider.isVertical()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -290,14 +290,14 @@ public class TypeClassifierTest extends ClassifierTest {
when(mDataProvider.isUp()).thenReturn(true);
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isUp()).thenReturn(false);
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
when(mDataProvider.isUp()).thenReturn(false);
when(mDataProvider.isRight()).thenReturn(true);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
}

View File

@@ -51,11 +51,11 @@ public class ZigZagClassifierTest extends ClassifierTest {
@Test
public void testPass_fewTouchesVertical() {
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
appendMoveEvent(0, 0);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
appendMoveEvent(0, 100);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -63,16 +63,16 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(0, 100);
appendMoveEvent(0, 200);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
public void testPass_fewTouchesHorizontal() {
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
appendMoveEvent(0, 0);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
appendMoveEvent(100, 0);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -80,7 +80,7 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(100, 0);
appendMoveEvent(200, 0);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@@ -89,7 +89,7 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(0, 100);
appendMoveEvent(0, 1);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -97,7 +97,7 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(100, 0);
appendMoveEvent(1, 0);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -105,7 +105,7 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(10, 10);
appendMoveEvent(20, 20);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -115,7 +115,7 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(5, 100);
appendMoveEvent(-5, 200);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -125,7 +125,7 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(100, 5);
appendMoveEvent(200, -5);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
}
@Test
@@ -135,7 +135,7 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(6, 10);
appendMoveEvent(-6, 20);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -145,7 +145,7 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(10, 5);
appendMoveEvent(20, -5);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -153,25 +153,25 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(100, 5);
appendMoveEvent(200, 10);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(100, 0);
appendMoveEvent(200, 10);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(100, -10);
appendMoveEvent(200, 10);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(100, -10);
appendMoveEvent(200, 50);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -179,25 +179,25 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(10, 50);
appendMoveEvent(8, 100);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(1, 800);
appendMoveEvent(2, 900);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(-10, 600);
appendMoveEvent(30, 700);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(40, 100);
appendMoveEvent(0, 101);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -205,25 +205,25 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(-10, 50);
appendMoveEvent(-24, 100);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(-20, 800);
appendMoveEvent(-20, 900);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(30, 600);
appendMoveEvent(-10, 700);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(-80, 100);
appendMoveEvent(-10, 101);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -231,25 +231,25 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(-120, 10);
appendMoveEvent(-200, 20);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(-20, 8);
appendMoveEvent(-40, 2);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(-500, -2);
appendMoveEvent(-600, 70);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(-80, 100);
appendMoveEvent(-100, 1);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -257,25 +257,25 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(-120, -10);
appendMoveEvent(-200, -20);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(-20, -8);
appendMoveEvent(-40, -2);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(-500, 2);
appendMoveEvent(-600, -70);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(-80, -100);
appendMoveEvent(-100, -1);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -283,25 +283,25 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(-12, -20);
appendMoveEvent(-20, -40);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(-20, -130);
appendMoveEvent(-40, -260);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(1, -100);
appendMoveEvent(-6, -200);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(-80, -100);
appendMoveEvent(-10, -110);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -309,25 +309,25 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(12, -20);
appendMoveEvent(20, -40);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(20, -130);
appendMoveEvent(40, -260);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(-1, -100);
appendMoveEvent(6, -200);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(80, -100);
appendMoveEvent(10, -110);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test
@@ -335,25 +335,25 @@ public class ZigZagClassifierTest extends ClassifierTest {
appendMoveEvent(0, 0);
appendMoveEvent(120, -20);
appendMoveEvent(200, -40);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(200, -13);
appendMoveEvent(400, -30);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(100, 10);
appendMoveEvent(600, -20);
assertThat(mClassifier.isFalseTouch(), is(false));
assertThat(mClassifier.classifyGesture().isFalse(), is(false));
resetDataProvider();
appendMoveEvent(0, 0);
appendMoveEvent(80, -100);
appendMoveEvent(100, -1);
assertThat(mClassifier.isFalseTouch(), is(true));
assertThat(mClassifier.classifyGesture().isFalse(), is(true));
}
@Test