1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.classifier;
18 
19 import static com.android.systemui.classifier.Classifier.BRIGHTNESS_SLIDER;
20 
21 import static com.google.common.truth.Truth.assertThat;
22 
23 import android.testing.AndroidTestingRunner;
24 
25 import androidx.test.filters.SmallTest;
26 
27 import com.android.systemui.util.DeviceConfigProxyFake;
28 
29 import org.junit.After;
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.junit.runner.RunWith;
33 
34 import java.util.Random;
35 
36 @SmallTest
37 @RunWith(AndroidTestingRunner.class)
38 public class ZigZagClassifierTest extends ClassifierTest {
39 
40     private FalsingClassifier mClassifier;
41 
42     @Before
setup()43     public void setup() {
44         super.setup();
45         mClassifier = new ZigZagClassifier(getDataProvider(), new DeviceConfigProxyFake());
46     }
47 
48     @After
tearDown()49     public void tearDown() {
50         super.tearDown();
51     }
52 
53     @Test
testPass_fewTouchesVertical()54     public void testPass_fewTouchesVertical() {
55         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
56         appendMoveEvent(0, 0);
57         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
58         appendMoveEvent(0, 100);
59         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
60     }
61 
62     @Test
testPass_vertical()63     public void testPass_vertical() {
64         appendMoveEvent(0, 0);
65         appendMoveEvent(0, 100);
66         appendMoveEvent(0, 200);
67         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
68     }
69 
70     @Test
testPass_dropClosingUpEvent()71     public void testPass_dropClosingUpEvent() {
72         appendMoveEvent(0, 0);
73         appendMoveEvent(0, 100);
74         appendMoveEvent(0, 200);
75         appendUpEvent(0, 180); // this event would push us over the maxDevianceY
76         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
77     }
78 
79     @Test
testPass_fewTouchesHorizontal()80     public void testPass_fewTouchesHorizontal() {
81         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
82         appendMoveEvent(0, 0);
83         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
84         appendMoveEvent(100, 0);
85         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
86     }
87 
88     @Test
testPass_horizontal()89     public void testPass_horizontal() {
90         appendMoveEvent(0, 0);
91         appendMoveEvent(100, 0);
92         appendMoveEvent(200, 0);
93         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
94     }
95 
96     @Test
testPass_brightnessSliderAlwaysPasses()97     public void testPass_brightnessSliderAlwaysPasses() {
98         appendMoveEvent(0, 0);
99         appendMoveEvent(0, 100);
100         appendMoveEvent(0, 1);
101         assertThat(mClassifier.classifyGesture(BRIGHTNESS_SLIDER, 0.5, 1).isFalse()).isFalse();
102     }
103 
104     @Test
testFail_minimumTouchesVertical()105     public void testFail_minimumTouchesVertical() {
106         appendMoveEvent(0, 0);
107         appendMoveEvent(0, 100);
108         appendMoveEvent(0, 1);
109         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
110     }
111 
112     @Test
testFail_minimumTouchesHorizontal()113     public void testFail_minimumTouchesHorizontal() {
114         appendMoveEvent(0, 0);
115         appendMoveEvent(100, 0);
116         appendMoveEvent(1, 0);
117         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
118     }
119 
120     @Test
testPass_fortyFiveDegreesStraight()121     public void testPass_fortyFiveDegreesStraight() {
122         appendMoveEvent(0, 0);
123         appendMoveEvent(10, 10);
124         appendMoveEvent(20, 20);
125         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
126     }
127 
128     @Test
testPass_horizontalZigZagVerticalStraight()129     public void testPass_horizontalZigZagVerticalStraight() {
130         // This test looks just like testFail_horizontalZigZagVerticalStraight but with
131         // a longer y range, making it look straighter.
132         appendMoveEvent(0, 0);
133         appendMoveEvent(5, 100);
134         appendMoveEvent(-5, 200);
135         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
136     }
137 
138     @Test
testPass_horizontalStraightVerticalZigZag()139     public void testPass_horizontalStraightVerticalZigZag() {
140         // This test looks just like testFail_horizontalStraightVerticalZigZag but with
141         // a longer x range, making it look straighter.
142         appendMoveEvent(0, 0);
143         appendMoveEvent(100, 5);
144         appendMoveEvent(200, -5);
145         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
146     }
147 
148     @Test
testFail_horizontalZigZagVerticalStraight()149     public void testFail_horizontalZigZagVerticalStraight() {
150         // This test looks just like testPass_horizontalZigZagVerticalStraight but with
151         // a shorter y range, making it look more crooked.
152         appendMoveEvent(0, 0);
153         appendMoveEvent(6, 10);
154         appendMoveEvent(-6, 20);
155         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
156     }
157 
158     @Test
testFail_horizontalStraightVerticalZigZag()159     public void testFail_horizontalStraightVerticalZigZag() {
160         // This test looks just like testPass_horizontalStraightVerticalZigZag but with
161         // a shorter x range, making it look more crooked.
162         appendMoveEvent(0, 0);
163         appendMoveEvent(10, 5);
164         appendMoveEvent(20, -5);
165         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
166     }
167 
168     @Test
test_between0And45()169     public void test_between0And45() {
170         appendMoveEvent(0, 0);
171         appendMoveEvent(100, 5);
172         appendMoveEvent(200, 10);
173         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
174 
175         resetDataProvider();
176         appendMoveEvent(0, 0);
177         appendMoveEvent(100, 0);
178         appendMoveEvent(200, 10);
179         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
180 
181         resetDataProvider();
182         appendMoveEvent(0, 0);
183         appendMoveEvent(100, -10);
184         appendMoveEvent(200, 10);
185         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
186 
187         resetDataProvider();
188         appendMoveEvent(0, 0);
189         appendMoveEvent(100, -10);
190         appendMoveEvent(200, 50);
191         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
192     }
193 
194     @Test
test_between45And90()195     public void test_between45And90() {
196         appendMoveEvent(0, 0);
197         appendMoveEvent(10, 50);
198         appendMoveEvent(8, 100);
199         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
200 
201         resetDataProvider();
202         appendMoveEvent(0, 0);
203         appendMoveEvent(1, 800);
204         appendMoveEvent(2, 900);
205         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
206 
207         resetDataProvider();
208         appendMoveEvent(0, 0);
209         appendMoveEvent(-10, 600);
210         appendMoveEvent(30, 700);
211         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
212 
213         resetDataProvider();
214         appendMoveEvent(0, 0);
215         appendMoveEvent(40, 100);
216         appendMoveEvent(0, 101);
217         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
218     }
219 
220     @Test
test_between90And135()221     public void test_between90And135() {
222         appendMoveEvent(0, 0);
223         appendMoveEvent(-10, 50);
224         appendMoveEvent(-24, 100);
225         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
226 
227         resetDataProvider();
228         appendMoveEvent(0, 0);
229         appendMoveEvent(-20, 800);
230         appendMoveEvent(-20, 900);
231         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
232 
233         resetDataProvider();
234         appendMoveEvent(0, 0);
235         appendMoveEvent(30, 600);
236         appendMoveEvent(-10, 700);
237         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
238 
239         resetDataProvider();
240         appendMoveEvent(0, 0);
241         appendMoveEvent(-80, 100);
242         appendMoveEvent(-10, 101);
243         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
244     }
245 
246     @Test
test_between135And180()247     public void test_between135And180() {
248         appendMoveEvent(0, 0);
249         appendMoveEvent(-120, 10);
250         appendMoveEvent(-200, 20);
251         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
252 
253         resetDataProvider();
254         appendMoveEvent(0, 0);
255         appendMoveEvent(-20, 8);
256         appendMoveEvent(-40, 2);
257         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
258 
259         resetDataProvider();
260         appendMoveEvent(0, 0);
261         appendMoveEvent(-500, -2);
262         appendMoveEvent(-600, 70);
263         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
264 
265         resetDataProvider();
266         appendMoveEvent(0, 0);
267         appendMoveEvent(-80, 100);
268         appendMoveEvent(-100, 1);
269         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
270     }
271 
272     @Test
test_between180And225()273     public void test_between180And225() {
274         appendMoveEvent(0, 0);
275         appendMoveEvent(-120, -10);
276         appendMoveEvent(-200, -20);
277         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
278 
279         resetDataProvider();
280         appendMoveEvent(0, 0);
281         appendMoveEvent(-20, -8);
282         appendMoveEvent(-40, -2);
283         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
284 
285         resetDataProvider();
286         appendMoveEvent(0, 0);
287         appendMoveEvent(-500, 2);
288         appendMoveEvent(-600, -70);
289         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
290 
291         resetDataProvider();
292         appendMoveEvent(0, 0);
293         appendMoveEvent(-80, -100);
294         appendMoveEvent(-100, -1);
295         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
296     }
297 
298     @Test
test_between225And270()299     public void test_between225And270() {
300         appendMoveEvent(0, 0);
301         appendMoveEvent(-12, -20);
302         appendMoveEvent(-20, -40);
303         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
304 
305         resetDataProvider();
306         appendMoveEvent(0, 0);
307         appendMoveEvent(-20, -130);
308         appendMoveEvent(-40, -260);
309         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
310 
311         resetDataProvider();
312         appendMoveEvent(0, 0);
313         appendMoveEvent(1, -100);
314         appendMoveEvent(-6, -200);
315         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
316 
317         resetDataProvider();
318         appendMoveEvent(0, 0);
319         appendMoveEvent(-80, -100);
320         appendMoveEvent(-10, -110);
321         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
322     }
323 
324     @Test
test_between270And315()325     public void test_between270And315() {
326         appendMoveEvent(0, 0);
327         appendMoveEvent(12, -20);
328         appendMoveEvent(20, -40);
329         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
330 
331         resetDataProvider();
332         appendMoveEvent(0, 0);
333         appendMoveEvent(20, -130);
334         appendMoveEvent(40, -260);
335         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
336 
337         resetDataProvider();
338         appendMoveEvent(0, 0);
339         appendMoveEvent(-1, -100);
340         appendMoveEvent(6, -200);
341         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
342 
343         resetDataProvider();
344         appendMoveEvent(0, 0);
345         appendMoveEvent(80, -100);
346         appendMoveEvent(10, -110);
347         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
348     }
349 
350     @Test
test_between315And360()351     public void test_between315And360() {
352         appendMoveEvent(0, 0);
353         appendMoveEvent(120, -20);
354         appendMoveEvent(200, -40);
355         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
356 
357         resetDataProvider();
358         appendMoveEvent(0, 0);
359         appendMoveEvent(200, -13);
360         appendMoveEvent(400, -30);
361         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
362 
363         resetDataProvider();
364         appendMoveEvent(0, 0);
365         appendMoveEvent(100, 10);
366         appendMoveEvent(600, -20);
367         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isFalse();
368 
369         resetDataProvider();
370         appendMoveEvent(0, 0);
371         appendMoveEvent(80, -100);
372         appendMoveEvent(100, -1);
373         assertThat(mClassifier.classifyGesture(0, 0.5, 1).isFalse()).isTrue();
374     }
375 
376     @Test
test_randomOrigins()377     public void test_randomOrigins() {
378         // The purpose of this test is to try all the other tests from different starting points.
379         // We use a pre-determined seed to make this test repeatable.
380         Random rand = new Random(23);
381         for (int i = 0; i < 100; i++) {
382             setOffsetX(rand.nextInt(2000) - 1000);
383             setOffsetY(rand.nextInt(2000) - 1000);
384             try {
385                 resetDataProvider();
386                 testPass_fewTouchesVertical();
387                 resetDataProvider();
388                 testPass_vertical();
389                 resetDataProvider();
390                 testFail_horizontalStraightVerticalZigZag();
391                 resetDataProvider();
392                 testFail_horizontalZigZagVerticalStraight();
393                 resetDataProvider();
394                 testFail_minimumTouchesHorizontal();
395                 resetDataProvider();
396                 testFail_minimumTouchesVertical();
397                 resetDataProvider();
398                 testPass_fewTouchesHorizontal();
399                 resetDataProvider();
400                 testPass_fortyFiveDegreesStraight();
401                 resetDataProvider();
402                 testPass_horizontal();
403                 resetDataProvider();
404                 testPass_horizontalStraightVerticalZigZag();
405                 resetDataProvider();
406                 testPass_horizontalZigZagVerticalStraight();
407                 resetDataProvider();
408                 test_between0And45();
409                 resetDataProvider();
410                 test_between45And90();
411                 resetDataProvider();
412                 test_between90And135();
413                 resetDataProvider();
414                 test_between135And180();
415                 resetDataProvider();
416                 test_between180And225();
417                 resetDataProvider();
418                 test_between225And270();
419                 resetDataProvider();
420                 test_between270And315();
421                 resetDataProvider();
422                 test_between315And360();
423             } catch (AssertionError e) {
424                 throw new AssertionError("Random origin failure in iteration " + i, e);
425             }
426         }
427     }
428 }
429