Add ZigZagClassifier to the BrightLineFalsingManager.
This rejects swipes that wiggle around too much. Swipes should be mostly straight. Bug: 111394067 Test: atest SystemUITests Change-Id: I43aa1cc62abb47ce43423c3c7c8e58c14dc0db03
This commit is contained in:
@@ -72,6 +72,7 @@ public class BrightLineFalsingManager implements FalsingManager {
|
||||
mClassifiers.add(new DiagonalClassifier(mDataProvider));
|
||||
mClassifiers.add(distanceClassifier);
|
||||
mClassifiers.add(proximityClassifier);
|
||||
mClassifiers.add(new ZigZagClassifier(mDataProvider));
|
||||
}
|
||||
|
||||
private void registerSensors() {
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.brightline;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Penalizes gestures that change direction in either the x or y too much.
|
||||
*/
|
||||
class ZigZagClassifier extends FalsingClassifier {
|
||||
|
||||
// Define how far one can move back and forth over one inch of travel before being falsed.
|
||||
// `PRIMARY` defines how far one can deviate in the primary direction of travel. I.e. if you're
|
||||
// swiping vertically, you shouldn't have a lot of zig zag in the vertical direction. Since
|
||||
// most swipes will follow somewhat of a 'C' or 'S' shape, we allow more deviance along the
|
||||
// `SECONDARY` axis.
|
||||
private static final float MAX_X_PRIMARY_DEVIANCE = .05f;
|
||||
private static final float MAX_Y_PRIMARY_DEVIANCE = .05f;
|
||||
private static final float MAX_X_SECONDARY_DEVIANCE = .3f;
|
||||
private static final float MAX_Y_SECONDARY_DEVIANCE = .3f;
|
||||
|
||||
ZigZagClassifier(FalsingDataProvider dataProvider) {
|
||||
super(dataProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFalseTouch() {
|
||||
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.
|
||||
// Sum the absolute value of every dx and dy along the gesture. Compare this with the dx
|
||||
// and dy
|
||||
// between the first and last point.
|
||||
// For horizontal lines, the difference in the x direction should be small.
|
||||
// For vertical lines, the difference in the y direction should be small.
|
||||
|
||||
if (motionEvents.size() < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Point> rotatedPoints;
|
||||
if (isHorizontal()) {
|
||||
rotatedPoints = rotateHorizontal();
|
||||
} else {
|
||||
rotatedPoints = rotateVertical();
|
||||
}
|
||||
|
||||
float actualDx = Math
|
||||
.abs(rotatedPoints.get(0).x - rotatedPoints.get(rotatedPoints.size() - 1).x);
|
||||
float actualDy = Math
|
||||
.abs(rotatedPoints.get(0).y - rotatedPoints.get(rotatedPoints.size() - 1).y);
|
||||
logDebug("Actual: (" + actualDx + "," + actualDy + ")");
|
||||
float runningAbsDx = 0;
|
||||
float runningAbsDy = 0;
|
||||
float pX = 0;
|
||||
float pY = 0;
|
||||
boolean firstLoop = true;
|
||||
for (Point point : rotatedPoints) {
|
||||
if (firstLoop) {
|
||||
pX = point.x;
|
||||
pY = point.y;
|
||||
firstLoop = false;
|
||||
continue;
|
||||
}
|
||||
runningAbsDx += Math.abs(point.x - pX);
|
||||
runningAbsDy += Math.abs(point.y - pY);
|
||||
pX = point.x;
|
||||
pY = point.y;
|
||||
logDebug("(x, y, runningAbsDx, runningAbsDy) - (" + pX + ", " + pY + ", " + runningAbsDx
|
||||
+ ", " + runningAbsDy + ")");
|
||||
}
|
||||
|
||||
float devianceX = runningAbsDx - actualDx;
|
||||
float devianceY = runningAbsDy - actualDy;
|
||||
float distanceXIn = actualDx / getXdpi();
|
||||
float distanceYIn = actualDy / getYdpi();
|
||||
float totalDistanceIn = (float) Math
|
||||
.sqrt(distanceXIn * distanceXIn + distanceYIn * distanceYIn);
|
||||
|
||||
float maxXDeviance;
|
||||
float maxYDeviance;
|
||||
if (actualDx > actualDy) {
|
||||
maxXDeviance = MAX_X_PRIMARY_DEVIANCE * totalDistanceIn * getXdpi();
|
||||
maxYDeviance = MAX_Y_SECONDARY_DEVIANCE * totalDistanceIn * getYdpi();
|
||||
} else {
|
||||
maxXDeviance = MAX_X_SECONDARY_DEVIANCE * totalDistanceIn * getXdpi();
|
||||
maxYDeviance = MAX_Y_PRIMARY_DEVIANCE * totalDistanceIn * getYdpi();
|
||||
}
|
||||
|
||||
logDebug("Straightness Deviance: (" + devianceX + "," + devianceY + ") vs "
|
||||
+ "(" + maxXDeviance + "," + maxYDeviance + ")");
|
||||
return devianceX > maxXDeviance || devianceY > maxYDeviance;
|
||||
}
|
||||
|
||||
private float getAtan2LastPoint() {
|
||||
MotionEvent firstEvent = getFirstMotionEvent();
|
||||
MotionEvent lastEvent = getLastMotionEvent();
|
||||
float offsetX = firstEvent.getX();
|
||||
float offsetY = firstEvent.getY();
|
||||
float lastX = lastEvent.getX() - offsetX;
|
||||
float lastY = lastEvent.getY() - offsetY;
|
||||
|
||||
return (float) Math.atan2(lastY, lastX);
|
||||
}
|
||||
|
||||
private List<Point> rotateVertical() {
|
||||
// Calculate the angle relative to the y axis.
|
||||
double angle = Math.PI / 2 - getAtan2LastPoint();
|
||||
logDebug("Rotating to vertical by: " + angle);
|
||||
return rotateMotionEvents(getRecentMotionEvents(), -angle);
|
||||
}
|
||||
|
||||
private List<Point> rotateHorizontal() {
|
||||
// Calculate the angle relative to the x axis.
|
||||
double angle = getAtan2LastPoint();
|
||||
logDebug("Rotating to horizontal by: " + angle);
|
||||
return rotateMotionEvents(getRecentMotionEvents(), angle);
|
||||
}
|
||||
|
||||
private List<Point> rotateMotionEvents(List<MotionEvent> motionEvents, double angle) {
|
||||
List<Point> points = new ArrayList<>();
|
||||
double cosAngle = Math.cos(angle);
|
||||
double sinAngle = Math.sin(angle);
|
||||
MotionEvent firstEvent = motionEvents.get(0);
|
||||
float offsetX = firstEvent.getX();
|
||||
float offsetY = firstEvent.getY();
|
||||
for (MotionEvent motionEvent : motionEvents) {
|
||||
float x = motionEvent.getX() - offsetX;
|
||||
float y = motionEvent.getY() - offsetY;
|
||||
double rotatedX = cosAngle * x + sinAngle * y + offsetX;
|
||||
double rotatedY = -sinAngle * x + cosAngle * y + offsetY;
|
||||
points.add(new Point((int) rotatedX, (int) rotatedY));
|
||||
}
|
||||
|
||||
MotionEvent lastEvent = motionEvents.get(motionEvents.size() - 1);
|
||||
Point firstPoint = points.get(0);
|
||||
Point lastPoint = points.get(points.size() - 1);
|
||||
logDebug(
|
||||
"Before: (" + firstEvent.getX() + "," + firstEvent.getY() + "), ("
|
||||
+ lastEvent.getX() + ","
|
||||
+ lastEvent.getY() + ")");
|
||||
logDebug(
|
||||
"After: (" + firstPoint.x + "," + firstPoint.y + "), (" + lastPoint.x + ","
|
||||
+ lastPoint.y
|
||||
+ ")");
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,467 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.brightline;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class ZigZagClassifierTest extends SysuiTestCase {
|
||||
|
||||
private static final long NS_PER_MS = 1000000;
|
||||
|
||||
@Mock
|
||||
private FalsingDataProvider mDataProvider;
|
||||
private FalsingClassifier mClassifier;
|
||||
private List<MotionEvent> mMotionEvents = new ArrayList<>();
|
||||
private float mOffsetX = 0;
|
||||
private float mOffsetY = 0;
|
||||
private float mDx;
|
||||
private float mDy;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mDataProvider.getXdpi()).thenReturn(100f);
|
||||
when(mDataProvider.getYdpi()).thenReturn(100f);
|
||||
when(mDataProvider.getRecentMotionEvents()).thenReturn(mMotionEvents);
|
||||
mClassifier = new ZigZagClassifier(mDataProvider);
|
||||
|
||||
|
||||
// Calculate the response to these calls on the fly, otherwise Mockito gets bogged down
|
||||
// everytime we call appendMotionEvent.
|
||||
when(mDataProvider.getFirstRecentMotionEvent()).thenAnswer(
|
||||
(Answer<MotionEvent>) invocation -> mMotionEvents.get(0));
|
||||
when(mDataProvider.getLastMotionEvent()).thenAnswer(
|
||||
(Answer<MotionEvent>) invocation -> mMotionEvents.get(mMotionEvents.size() - 1));
|
||||
when(mDataProvider.isHorizontal()).thenAnswer(
|
||||
(Answer<Boolean>) invocation -> Math.abs(mDy) < Math.abs(mDx));
|
||||
when(mDataProvider.isVertical()).thenAnswer(
|
||||
(Answer<Boolean>) invocation -> Math.abs(mDy) > Math.abs(mDx));
|
||||
when(mDataProvider.isRight()).thenAnswer((Answer<Boolean>) invocation -> mDx > 0);
|
||||
when(mDataProvider.isUp()).thenAnswer((Answer<Boolean>) invocation -> mDy < 0);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
for (MotionEvent motionEvent : mMotionEvents) {
|
||||
motionEvent.recycle();
|
||||
}
|
||||
mMotionEvents.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPass_fewTouchesVertical() {
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
appendMotionEvent(0, 0);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
appendMotionEvent(0, 100);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPass_vertical() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(0, 100);
|
||||
appendMotionEvent(0, 200);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPass_fewTouchesHorizontal() {
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
appendMotionEvent(0, 0);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
appendMotionEvent(100, 0);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPass_horizontal() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(100, 0);
|
||||
appendMotionEvent(200, 0);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFail_minimumTouchesVertical() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(0, 100);
|
||||
appendMotionEvent(0, 1);
|
||||
assertThat(mClassifier.isFalseTouch(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFail_minimumTouchesHorizontal() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(100, 0);
|
||||
appendMotionEvent(1, 0);
|
||||
assertThat(mClassifier.isFalseTouch(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPass_fortyFiveDegreesStraight() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(10, 10);
|
||||
appendMotionEvent(20, 20);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPass_horizontalZigZagVerticalStraight() {
|
||||
// This test looks just like testFail_horizontalZigZagVerticalStraight but with
|
||||
// a longer y range, making it look straighter.
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(5, 100);
|
||||
appendMotionEvent(-5, 200);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPass_horizontalStraightVerticalZigZag() {
|
||||
// This test looks just like testFail_horizontalStraightVerticalZigZag but with
|
||||
// a longer x range, making it look straighter.
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(100, 5);
|
||||
appendMotionEvent(200, -5);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFail_horizontalZigZagVerticalStraight() {
|
||||
// This test looks just like testPass_horizontalZigZagVerticalStraight but with
|
||||
// a shorter y range, making it look more crooked.
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(5, 10);
|
||||
appendMotionEvent(-5, 20);
|
||||
assertThat(mClassifier.isFalseTouch(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFail_horizontalStraightVerticalZigZag() {
|
||||
// This test looks just like testPass_horizontalStraightVerticalZigZag but with
|
||||
// a shorter x range, making it look more crooked.
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(10, 5);
|
||||
appendMotionEvent(20, -5);
|
||||
assertThat(mClassifier.isFalseTouch(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_between0And45() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(100, 5);
|
||||
appendMotionEvent(200, 10);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(100, 0);
|
||||
appendMotionEvent(200, 10);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(100, -10);
|
||||
appendMotionEvent(200, 10);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(100, -10);
|
||||
appendMotionEvent(200, 50);
|
||||
assertThat(mClassifier.isFalseTouch(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_between45And90() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(10, 50);
|
||||
appendMotionEvent(8, 100);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(1, 800);
|
||||
appendMotionEvent(2, 900);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-10, 600);
|
||||
appendMotionEvent(30, 700);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(40, 100);
|
||||
appendMotionEvent(0, 101);
|
||||
assertThat(mClassifier.isFalseTouch(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_between90And135() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-10, 50);
|
||||
appendMotionEvent(-24, 100);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-20, 800);
|
||||
appendMotionEvent(-20, 900);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(30, 600);
|
||||
appendMotionEvent(-10, 700);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-80, 100);
|
||||
appendMotionEvent(-10, 101);
|
||||
assertThat(mClassifier.isFalseTouch(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_between135And180() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-120, 10);
|
||||
appendMotionEvent(-200, 20);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-20, 8);
|
||||
appendMotionEvent(-40, 2);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-500, -2);
|
||||
appendMotionEvent(-600, 70);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-80, 100);
|
||||
appendMotionEvent(-100, 1);
|
||||
assertThat(mClassifier.isFalseTouch(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_between180And225() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-120, -10);
|
||||
appendMotionEvent(-200, -20);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-20, -8);
|
||||
appendMotionEvent(-40, -2);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-500, 2);
|
||||
appendMotionEvent(-600, -70);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-80, -100);
|
||||
appendMotionEvent(-100, -1);
|
||||
assertThat(mClassifier.isFalseTouch(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_between225And270() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-12, -20);
|
||||
appendMotionEvent(-20, -40);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-20, -130);
|
||||
appendMotionEvent(-40, -260);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(1, -100);
|
||||
appendMotionEvent(-6, -200);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-80, -100);
|
||||
appendMotionEvent(-10, -110);
|
||||
assertThat(mClassifier.isFalseTouch(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_between270And315() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(12, -20);
|
||||
appendMotionEvent(20, -40);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(20, -130);
|
||||
appendMotionEvent(40, -260);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(-1, -100);
|
||||
appendMotionEvent(6, -200);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(80, -100);
|
||||
appendMotionEvent(10, -110);
|
||||
assertThat(mClassifier.isFalseTouch(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_between315And360() {
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(120, -20);
|
||||
appendMotionEvent(200, -40);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(200, -13);
|
||||
appendMotionEvent(400, -30);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(100, 10);
|
||||
appendMotionEvent(600, -20);
|
||||
assertThat(mClassifier.isFalseTouch(), is(false));
|
||||
|
||||
mMotionEvents.clear();
|
||||
appendMotionEvent(0, 0);
|
||||
appendMotionEvent(80, -100);
|
||||
appendMotionEvent(100, -1);
|
||||
assertThat(mClassifier.isFalseTouch(), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_randomOrigins() {
|
||||
// The purpose of this test is to try all the other tests from different starting points.
|
||||
// We use a pre-determined seed to make this test repeatable.
|
||||
Random rand = new Random(23);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
mOffsetX = rand.nextInt(2000) - 1000;
|
||||
mOffsetY = rand.nextInt(2000) - 1000;
|
||||
try {
|
||||
mMotionEvents.clear();
|
||||
testPass_fewTouchesVertical();
|
||||
mMotionEvents.clear();
|
||||
testPass_vertical();
|
||||
mMotionEvents.clear();
|
||||
testFail_horizontalStraightVerticalZigZag();
|
||||
mMotionEvents.clear();
|
||||
testFail_horizontalZigZagVerticalStraight();
|
||||
mMotionEvents.clear();
|
||||
testFail_minimumTouchesHorizontal();
|
||||
mMotionEvents.clear();
|
||||
testFail_minimumTouchesVertical();
|
||||
mMotionEvents.clear();
|
||||
testPass_fewTouchesHorizontal();
|
||||
mMotionEvents.clear();
|
||||
testPass_fortyFiveDegreesStraight();
|
||||
mMotionEvents.clear();
|
||||
testPass_horizontal();
|
||||
mMotionEvents.clear();
|
||||
testPass_horizontalStraightVerticalZigZag();
|
||||
mMotionEvents.clear();
|
||||
testPass_horizontalZigZagVerticalStraight();
|
||||
mMotionEvents.clear();
|
||||
test_between0And45();
|
||||
mMotionEvents.clear();
|
||||
test_between45And90();
|
||||
mMotionEvents.clear();
|
||||
test_between90And135();
|
||||
mMotionEvents.clear();
|
||||
test_between135And180();
|
||||
mMotionEvents.clear();
|
||||
test_between180And225();
|
||||
mMotionEvents.clear();
|
||||
test_between225And270();
|
||||
mMotionEvents.clear();
|
||||
test_between270And315();
|
||||
mMotionEvents.clear();
|
||||
test_between315And360();
|
||||
} catch (AssertionError e) {
|
||||
throw new AssertionError("Random origin failure in iteration " + i, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void appendMotionEvent(float x, float y) {
|
||||
x += mOffsetX;
|
||||
y += mOffsetY;
|
||||
|
||||
long eventTime = mMotionEvents.size() + 1;
|
||||
MotionEvent motionEvent = MotionEvent.obtain(1, eventTime, MotionEvent.ACTION_DOWN, x, y,
|
||||
0);
|
||||
mMotionEvents.add(motionEvent);
|
||||
|
||||
mDx = mDataProvider.getFirstRecentMotionEvent().getX()
|
||||
- mDataProvider.getLastMotionEvent().getX();
|
||||
mDy = mDataProvider.getFirstRecentMotionEvent().getY()
|
||||
- mDataProvider.getLastMotionEvent().getY();
|
||||
|
||||
mClassifier.onTouchEvent(motionEvent);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user