xref: /aosp_15_r20/external/libchrome-gestures/src/immediate_interpreter_unittest.cc (revision aed3e5085e770be5b69ce25295ecf6ddf906af95)
1 // Copyright 2012 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stdio.h>
6 #include <string>
7 #include <vector>
8 
9 #include <gtest/gtest.h>
10 
11 #include "include/gestures.h"
12 #include "include/immediate_interpreter.h"
13 #include "include/string_util.h"
14 #include "include/unittest_util.h"
15 #include "include/util.h"
16 
17 namespace gestures {
18 
19 using std::string;
20 
21 class ImmediateInterpreterTest : public ::testing::Test {};
22 
TEST(ImmediateInterpreterTest,ScrollEventTest)23 TEST(ImmediateInterpreterTest, ScrollEventTest) {
24   ScrollEvent ev1 = {1.0, 2.0, 3.0};
25   ScrollEvent ev2 = {10.0, 20.0, 30.0};
26   ScrollEvent ev3 = ScrollEvent::Add(ev1, ev2);
27   EXPECT_EQ(11.0, ev3.dx);
28   EXPECT_EQ(22.0, ev3.dy);
29   EXPECT_EQ(33.0, ev3.dt);
30 
31   ScrollEventBuffer evbuf(2);
32   evbuf.Insert(1.0, 2.0, 3.0, 0.0);
33   ev1 = evbuf.Get(0);
34   EXPECT_EQ(1.0, ev1.dx);
35   EXPECT_EQ(2.0, ev1.dy);
36   EXPECT_EQ(3.0, ev1.dt);
37   ev1 = evbuf.Get(3);
38   EXPECT_EQ(0.0, ev1.dx);
39   EXPECT_EQ(0.0, ev1.dy);
40   EXPECT_EQ(0.0, ev1.dt);
41 }
42 
TEST(ImmediateInterpreterTest,HardwareStateBufferTest)43 TEST(ImmediateInterpreterTest, HardwareStateBufferTest) {
44   HardwareStateBuffer hsb(10);
45   hsb.Reset(0);
46   EXPECT_EQ(hsb.Size(), 10);
47 }
48 
TEST(ImmediateInterpreterTest,ScrollManagerTest)49 TEST(ImmediateInterpreterTest, ScrollManagerTest) {
50   PropRegistry my_prop_reg;
51   ScrollManager sm(&my_prop_reg);
52   ScrollEventBuffer scroll_buffer(2);
53   ScrollEvent ev;
54 
55   sm.RegressScrollVelocity(scroll_buffer, 1, &ev);
56   EXPECT_EQ(0.0, ev.dx);
57   EXPECT_EQ(0.0, ev.dy);
58   EXPECT_EQ(1.0, ev.dt);
59 }
60 
TEST(ImmediateInterpreterTest,MoveDownTest)61 TEST(ImmediateInterpreterTest, MoveDownTest) {
62   ImmediateInterpreter ii(nullptr, nullptr);
63 
64   HardwareProperties hwprops = {
65     .right = 1000,
66     .bottom = 1000,
67     .res_x = 500,
68     .res_y = 500,
69     .orientation_minimum = -1,
70     .orientation_maximum = 2,
71     .max_finger_cnt = 2,
72     .max_touch_cnt = 5,
73     .supports_t5r2 = 0,
74     .support_semi_mt = 0,
75     .is_button_pad = 1,
76     .has_wheel = 0,
77     .wheel_is_hi_res = 0,
78     .is_haptic_pad = 0,
79   };
80   TestInterpreterWrapper wrapper(&ii, &hwprops);
81 
82   FingerState finger_states[] = {
83     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
84     {0, 0, 0, 0, 1, 0, 10, 10, 1, 0},
85     {0, 0, 0, 0, 1, 0, 10, 20, 1, 0},
86     {0, 0, 0, 0, 1, 0, 20, 20, 1, 0}
87   };
88   HardwareState hardware_states[] = {
89     // time, buttons down, finger count, finger states pointer
90     make_hwstate(200000, 0, 1, 1, &finger_states[0]),
91     make_hwstate(210000, 0, 1, 1, &finger_states[1]),
92     make_hwstate(220000, 0, 1, 1, &finger_states[2]),
93     make_hwstate(230000, 0, 0, 0, nullptr),
94     make_hwstate(240000, 0, 0, 0, nullptr),
95   };
96 
97   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[0], nullptr));
98 
99   Gesture* gs = wrapper.SyncInterpret(hardware_states[1], nullptr);
100   ASSERT_NE(nullptr, gs);
101   EXPECT_EQ(kGestureTypeMove, gs->type);
102   EXPECT_EQ(0, gs->details.move.dx);
103   EXPECT_EQ(10, gs->details.move.dy);
104   EXPECT_EQ(200000, gs->start_time);
105   EXPECT_EQ(210000, gs->end_time);
106 
107   gs = wrapper.SyncInterpret(hardware_states[2], nullptr);
108   EXPECT_NE(nullptr, gs);
109   EXPECT_EQ(kGestureTypeMove, gs->type);
110   EXPECT_EQ(10, gs->details.move.dx);
111   EXPECT_EQ(0, gs->details.move.dy);
112   EXPECT_EQ(210000, gs->start_time);
113   EXPECT_EQ(220000, gs->end_time);
114 
115   EXPECT_EQ(nullptr,
116             wrapper.SyncInterpret(hardware_states[3], nullptr));
117   EXPECT_EQ(nullptr,
118             wrapper.SyncInterpret(hardware_states[4], nullptr));
119 }
120 
TEST(ImmediateInterpreterTest,MoveUpWithRestingThumbTest)121 TEST(ImmediateInterpreterTest, MoveUpWithRestingThumbTest) {
122   ImmediateInterpreter ii(nullptr, nullptr);
123 
124   HardwareProperties hwprops = {
125     .right = 1000,
126     .bottom = 1000,
127     .res_x = 50,
128     .res_y = 50,
129     .orientation_minimum = -1,
130     .orientation_maximum = 2,
131     .max_finger_cnt = 2,
132     .max_touch_cnt = 5,
133     .supports_t5r2 = 0,
134     .support_semi_mt = 0,
135     .is_button_pad = 1,
136     .has_wheel = 0,
137     .wheel_is_hi_res = 0,
138     .is_haptic_pad = 0,
139   };
140   TestInterpreterWrapper wrapper(&ii, &hwprops);
141 
142   FingerState finger_states[] = {
143     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
144     {0, 0, 0, 0, 10, 0, 500, 999, 1, 0},
145     {0, 0, 0, 0, 10, 0, 500, 950, 2, 0},
146     {0, 0, 0, 0, 10, 0, 500, 999, 1, 0},
147     {0, 0, 0, 0, 10, 0, 500, 940, 2, 0},
148     {0, 0, 0, 0, 10, 0, 500, 999, 1, 0},
149     {0, 0, 0, 0, 10, 0, 500, 930, 2, 0}
150   };
151   HardwareState hardware_states[] = {
152     // time, buttons down, finger count, finger states pointer
153     make_hwstate(200000, 0, 2, 2, &finger_states[0]),
154     make_hwstate(210000, 0, 2, 2, &finger_states[2]),
155     make_hwstate(220000, 0, 2, 2, &finger_states[4]),
156     make_hwstate(230000, 0, 0, 0, nullptr),
157     make_hwstate(240000, 0, 0, 0, nullptr),
158   };
159 
160   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[0], nullptr));
161 
162   Gesture* gs = wrapper.SyncInterpret(hardware_states[1], nullptr);
163   ASSERT_NE(nullptr, gs);
164   EXPECT_EQ(kGestureTypeMove, gs->type);
165   EXPECT_EQ(0, gs->details.move.dx);
166   EXPECT_EQ(-10, gs->details.move.dy);
167   EXPECT_EQ(200000, gs->start_time);
168   EXPECT_EQ(210000, gs->end_time);
169 
170   gs = wrapper.SyncInterpret(hardware_states[2], nullptr);
171   EXPECT_NE(nullptr, gs);
172   EXPECT_EQ(kGestureTypeMove, gs->type);
173   EXPECT_EQ(0, gs->details.move.dx);
174   EXPECT_EQ(-10, gs->details.move.dy);
175   EXPECT_EQ(210000, gs->start_time);
176   EXPECT_EQ(220000, gs->end_time);
177 
178   EXPECT_EQ(nullptr,
179             wrapper.SyncInterpret(hardware_states[3], nullptr));
180   EXPECT_EQ(nullptr,
181             wrapper.SyncInterpret(hardware_states[4], nullptr));
182 }
183 
TEST(ImmediateInterpreterTest,SemiMtScrollUpWithRestingThumbTest)184 TEST(ImmediateInterpreterTest, SemiMtScrollUpWithRestingThumbTest) {
185   ImmediateInterpreter ii(nullptr, nullptr);
186   HardwareProperties hwprops = {
187     .right = 1000,
188     .bottom = 1000,
189     .res_x = 20,
190     .res_y = 20,
191     .orientation_minimum = -1,
192     .orientation_maximum = 2,
193     .max_finger_cnt = 2,
194     .max_touch_cnt = 3,
195     .supports_t5r2 = 0,
196     .support_semi_mt = 1,
197     .is_button_pad = 1,
198     .has_wheel = 0,
199     .wheel_is_hi_res = 0,
200     .is_haptic_pad = 0,
201   };
202   TestInterpreterWrapper wrapper(&ii, &hwprops);
203 
204   FingerState finger_states[] = {
205     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
206     {0, 0, 0, 0, 100, 0, 50, 950, 1, 0},
207     {0, 0, 0, 0, 100, 0, 415, 900, 2, 0},
208 
209     {0, 0, 0, 0, 100, 0, 50, 950, 1, 0},
210     {0, 0, 0, 0, 100, 0, 415, 800, 2, 0},
211 
212     {0, 0, 0, 0, 100, 0, 50, 950, 1, 0},
213     {0, 0, 0, 0, 100, 0, 415, 700, 2, 0},
214   };
215   HardwareState hardware_states[] = {
216     // time, buttons, finger count, touch count, finger states pointer
217     make_hwstate(0.200000, 0, 2, 3, &finger_states[0]),
218     make_hwstate(0.250000, 0, 2, 3, &finger_states[2]),
219     make_hwstate(0.300000, 0, 2, 3, &finger_states[4]),
220   };
221 
222   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[0], nullptr));
223 
224   Gesture* gs = wrapper.SyncInterpret(hardware_states[1], nullptr);
225   ASSERT_NE(nullptr, gs);
226   EXPECT_EQ(kGestureTypeScroll, gs->type);
227   EXPECT_FLOAT_EQ(0, gs->details.move.dx);
228   EXPECT_FLOAT_EQ(-100, gs->details.move.dy);
229   EXPECT_DOUBLE_EQ(0.200000, gs->start_time);
230   EXPECT_DOUBLE_EQ(0.250000, gs->end_time);
231 
232   gs = wrapper.SyncInterpret(hardware_states[2], nullptr);
233   ASSERT_NE(nullptr, gs);
234   EXPECT_EQ(kGestureTypeScroll, gs->type);
235   EXPECT_FLOAT_EQ(0, gs->details.move.dx);
236   EXPECT_FLOAT_EQ(-100, gs->details.move.dy);
237   EXPECT_DOUBLE_EQ(0.250000, gs->start_time);
238   EXPECT_DOUBLE_EQ(0.300000, gs->end_time);
239 }
240 
ScrollUpTest(float pressure_a,float pressure_b)241 void ScrollUpTest(float pressure_a, float pressure_b) {
242   ImmediateInterpreter ii(nullptr, nullptr);
243   HardwareProperties hwprops = {
244     .right = 1000,
245     .bottom = 1000,
246     .res_x = 20,
247     .res_y = 20,
248     .orientation_minimum = -1,
249     .orientation_maximum = 2,
250     .max_finger_cnt = 2,
251     .max_touch_cnt = 5,
252     .supports_t5r2 = 0,
253     .support_semi_mt = 0,
254     .is_button_pad = 1,
255     .has_wheel = 0,
256     .wheel_is_hi_res = 0,
257     .is_haptic_pad = 0,
258   };
259   TestInterpreterWrapper wrapper(&ii, &hwprops);
260 
261   float p_a = pressure_a;
262   float p_b = pressure_b;
263 
264   FingerState finger_states[] = {
265     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
266     {0, 0, 0, 0, p_a, 0, 400, 900, 1, 0},
267     {0, 0, 0, 0, p_b, 0, 415, 900, 2, 0},
268 
269     {0, 0, 0, 0, p_a, 0, 400, 800, 1, 0},
270     {0, 0, 0, 0, p_b, 0, 415, 800, 2, 0},
271 
272     {0, 0, 0, 0, p_a, 0, 400, 700, 1, 0},
273     {0, 0, 0, 0, p_b, 0, 415, 700, 2, 0},
274   };
275   HardwareState hardware_states[] = {
276     // time, buttons, finger count, touch count, finger states pointer
277     make_hwstate(0.200000, 0, 2, 2, &finger_states[0]),
278     make_hwstate(0.250000, 0, 2, 2, &finger_states[2]),
279     make_hwstate(0.300000, 0, 2, 2, &finger_states[4]),
280   };
281 
282   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[0], nullptr));
283 
284   Gesture* gs = wrapper.SyncInterpret(hardware_states[1], nullptr);
285   ASSERT_NE(nullptr, gs);
286   EXPECT_EQ(kGestureTypeScroll, gs->type);
287   EXPECT_FLOAT_EQ(0, gs->details.move.dx);
288   EXPECT_FLOAT_EQ(-100, gs->details.move.dy);
289   EXPECT_DOUBLE_EQ(0.200000, gs->start_time);
290   EXPECT_DOUBLE_EQ(0.250000, gs->end_time);
291 
292   gs = wrapper.SyncInterpret(hardware_states[2], nullptr);
293   ASSERT_NE(nullptr, gs);
294   EXPECT_EQ(kGestureTypeScroll, gs->type);
295   EXPECT_FLOAT_EQ(0, gs->details.move.dx);
296   EXPECT_FLOAT_EQ(-100, gs->details.move.dy);
297   EXPECT_DOUBLE_EQ(0.250000, gs->start_time);
298   EXPECT_DOUBLE_EQ(0.300000, gs->end_time);
299 }
300 
TEST(ImmediateInterpreterTest,ScrollUpTest)301 TEST(ImmediateInterpreterTest, ScrollUpTest) {
302   ScrollUpTest(24, 92);
303 }
304 
TEST(ImmediateInterpreterTest,FatFingerScrollUpTest)305 TEST(ImmediateInterpreterTest, FatFingerScrollUpTest) {
306   ScrollUpTest(125, 185);
307 }
308 
309 // Tests that a tap immediately after a scroll doesn't generate a click.
310 // Such a tap would be unrealistic to come from a human.
TEST(ImmediateInterpreterTest,ScrollThenFalseTapTest)311 TEST(ImmediateInterpreterTest, ScrollThenFalseTapTest) {
312   ImmediateInterpreter ii(nullptr, nullptr);
313   HardwareProperties hwprops = {
314     .right = 1000,
315     .bottom = 1000,
316     .res_x = 20,
317     .res_y = 20,
318     .orientation_minimum = -1,
319     .orientation_maximum = 2,
320     .max_finger_cnt = 2,
321     .max_touch_cnt = 5,
322     .supports_t5r2 = 0,
323     .support_semi_mt = 0,
324     .is_button_pad = 1,
325     .has_wheel = 0,
326     .wheel_is_hi_res = 0,
327     .is_haptic_pad = 0,
328   };
329   TestInterpreterWrapper wrapper(&ii, &hwprops);
330 
331   FingerState finger_states[] = {
332     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
333     {0, 0, 0, 0, 20, 0, 400, 900, 1, 0},
334     {0, 0, 0, 0, 20, 0, 415, 900, 2, 0},
335 
336     {0, 0, 0, 0, 20, 0, 400, 800, 1, 0},
337     {0, 0, 0, 0, 20, 0, 415, 800, 2, 0},
338 
339     {0, 0, 0, 0, 20, 0, 400, 700, 1, 0},
340     {0, 0, 0, 0, 20, 0, 415, 700, 2, 0},
341 
342     {0, 0, 0, 0, 20, 0, 400, 600, 3, 0},
343   };
344   HardwareState hardware_states[] = {
345     // time, buttons, finger count, touch count, finger states pointer
346     make_hwstate(0.200000, 0, 2, 2, &finger_states[0]),
347     make_hwstate(0.250000, 0, 2, 2, &finger_states[2]),
348     make_hwstate(0.300000, 0, 2, 2, &finger_states[4]),
349     make_hwstate(0.310000, 0, 0, 0, nullptr),
350     make_hwstate(0.320000, 0, 1, 1, &finger_states[6]),
351     make_hwstate(0.330000, 0, 0, 0, nullptr),
352   };
353 
354   ii.tap_enable_.val_ = 1;
355   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[0], nullptr));
356 
357   Gesture* gs = wrapper.SyncInterpret(hardware_states[1], nullptr);
358   ASSERT_NE(nullptr, gs);
359   EXPECT_EQ(kGestureTypeScroll, gs->type);
360   gs = wrapper.SyncInterpret(hardware_states[2], nullptr);
361   ASSERT_NE(nullptr, gs);
362   EXPECT_EQ(kGestureTypeScroll, gs->type);
363   gs = wrapper.SyncInterpret(hardware_states[3], nullptr);
364   ASSERT_NE(nullptr, gs);
365   EXPECT_EQ(kGestureTypeFling, gs->type);
366   gs = wrapper.SyncInterpret(hardware_states[4], nullptr);
367   ASSERT_EQ(nullptr, gs);
368   stime_t timeout = NO_DEADLINE;
369   gs = wrapper.SyncInterpret(hardware_states[5], &timeout);
370   ASSERT_EQ(nullptr, gs);
371   // If it were a tap, timeout would be > 0, but this shouldn't be a tap,
372   // so timeout should be negative still.
373   EXPECT_LT(timeout, 0.0);
374 }
375 
376 // Tests that a consistent scroll has predictable fling, and that increasing
377 // scrolls have a fling as least as fast the second to last scroll.
TEST(ImmediateInterpreterTest,FlingTest)378 TEST(ImmediateInterpreterTest, FlingTest) {
379   ImmediateInterpreter ii(nullptr, nullptr);
380   HardwareProperties hwprops = {
381     .right = 100,
382     .bottom = 100,
383     .res_x = 1,
384     .res_y = 1,
385     .orientation_minimum = -1,
386     .orientation_maximum = 2,
387     .max_finger_cnt = 2,
388     .max_touch_cnt = 5,
389     .supports_t5r2 = 0,
390     .support_semi_mt = 0,
391     .is_button_pad = 1,
392     .has_wheel = 0,
393     .wheel_is_hi_res = 0,
394     .is_haptic_pad = 0,
395   };
396   TestInterpreterWrapper wrapper(&ii, &hwprops);
397 
398   FingerState finger_states[] = {
399     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
400     // Consistent movement for 4 frames
401     {0, 0, 0, 0, 20, 0, 40, 20, 1, 0},
402     {0, 0, 0, 0, 20, 0, 60, 20, 2, 0},
403 
404     {0, 0, 0, 0, 20, 0, 40, 30, 1, 0},
405     {0, 0, 0, 0, 20, 0, 60, 30, 2, 0},
406 
407     {0, 0, 0, 0, 20, 0, 40, 40, 1, 0},
408     {0, 0, 0, 0, 20, 0, 60, 40, 2, 0},
409 
410     {0, 0, 0, 0, 20, 0, 40, 50, 1, 0},
411     {0, 0, 0, 0, 20, 0, 60, 50, 2, 0},
412 
413     // Increasing movement for 4 frames
414     {0, 0, 0, 0, 20, 0, 40, 20, 3, 0},
415     {0, 0, 0, 0, 20, 0, 60, 20, 4, 0},
416 
417     {0, 0, 0, 0, 20, 0, 40, 25, 3, 0},
418     {0, 0, 0, 0, 20, 0, 60, 25, 4, 0},
419 
420     {0, 0, 0, 0, 20, 0, 40, 35, 3, 0},
421     {0, 0, 0, 0, 20, 0, 60, 35, 4, 0},
422 
423     {0, 0, 0, 0, 20, 0, 40, 50, 3, 0},
424     {0, 0, 0, 0, 20, 0, 60, 50, 4, 0},
425   };
426   HardwareState hardware_states[] = {
427     // time, buttons, finger count, touch count, finger states pointer
428     make_hwstate(0.00, 0, 2, 2, &finger_states[0]),
429     make_hwstate(1.00, 0, 2, 2, &finger_states[0]),
430     make_hwstate(1.01, 0, 2, 2, &finger_states[2]),
431     make_hwstate(1.02, 0, 2, 2, &finger_states[4]),
432     make_hwstate(1.03, 0, 2, 2, &finger_states[6]),
433     make_hwstate(1.04, 0, 0, 0, nullptr),
434 
435     make_hwstate(3.00, 0, 2, 2, &finger_states[8]),
436     make_hwstate(4.00, 0, 2, 2, &finger_states[8]),
437     make_hwstate(4.01, 0, 2, 2, &finger_states[10]),
438     make_hwstate(4.02, 0, 2, 2, &finger_states[12]),
439     make_hwstate(4.03, 0, 2, 2, &finger_states[14]),
440     make_hwstate(4.04, 0, 0, 0, nullptr),
441   };
442 
443   size_t idx = 0;
444 
445   // Consistent movement
446   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[idx++], nullptr));
447   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[idx++], nullptr));
448 
449   Gesture* gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
450   ASSERT_NE(nullptr, gs);
451   EXPECT_EQ(kGestureTypeScroll, gs->type);
452   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
453   ASSERT_NE(nullptr, gs);
454   EXPECT_EQ(kGestureTypeScroll, gs->type);
455   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
456   ASSERT_NE(nullptr, gs);
457   EXPECT_EQ(kGestureTypeScroll, gs->type);
458   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
459   ASSERT_NE(nullptr, gs);
460   EXPECT_EQ(kGestureTypeFling, gs->type);
461   EXPECT_FLOAT_EQ(0, gs->details.fling.vx);
462   EXPECT_FLOAT_EQ(10 / 0.01, gs->details.fling.vy);
463 
464   // Increasing speed movement
465   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
466   EXPECT_EQ(nullptr, gs) << gs->String();
467   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
468   EXPECT_EQ(nullptr, gs) << gs->String();
469 
470   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
471   ASSERT_NE(nullptr, gs);
472   EXPECT_EQ(kGestureTypeScroll, gs->type);
473   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
474   ASSERT_NE(nullptr, gs);
475   EXPECT_EQ(kGestureTypeScroll, gs->type);
476   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
477   ASSERT_NE(nullptr, gs);
478   EXPECT_EQ(kGestureTypeScroll, gs->type);
479   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
480   ASSERT_NE(nullptr, gs);
481   EXPECT_EQ(kGestureTypeFling, gs->type);
482   EXPECT_FLOAT_EQ(0, gs->details.fling.vx);
483   EXPECT_FLOAT_EQ(1250, gs->details.fling.vy);
484 }
485 
486 // Tests that fingers that have been present a while, but are stationary,
487 // can be evaluated multiple times when they start moving.
TEST(ImmediateInterpreterTest,DelayedStartScrollTest)488 TEST(ImmediateInterpreterTest, DelayedStartScrollTest) {
489   ImmediateInterpreter ii(nullptr, nullptr);
490   HardwareProperties hwprops = {
491     .right = 100,
492     .bottom = 100,
493     .res_x = 1,
494     .res_y = 1,
495     .orientation_minimum = -1,
496     .orientation_maximum = 2,
497     .max_finger_cnt = 2,
498     .max_touch_cnt = 5,
499     .supports_t5r2 = 0,
500     .support_semi_mt = 0,
501     .is_button_pad = 1,
502     .has_wheel = 0,
503     .wheel_is_hi_res = 0,
504     .is_haptic_pad = 0,
505   };
506   TestInterpreterWrapper wrapper(&ii, &hwprops);
507 
508   FingerState finger_states[] = {
509     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
510     // Consistent movement for 4 frames
511     {0, 0, 0, 0, 20, 0, 40, 95, 1, 0},
512     {0, 0, 0, 0, 20, 0, 60, 95, 2, 0},
513 
514     {0, 0, 0, 0, 20, 0, 40, 95, 1, 0},
515     {0, 0, 0, 0, 20, 0, 60, 85, 2, 0},
516 
517     {0, 0, 0, 0, 20, 0, 40, 80, 1, 0},
518     {0, 0, 0, 0, 20, 0, 60, 75, 2, 0},
519   };
520   HardwareState hardware_states[] = {
521     // time, buttons, finger count, touch count, finger states pointer
522     make_hwstate(1.00, 0, 2, 2, &finger_states[0]),
523     make_hwstate(2.00, 0, 2, 2, &finger_states[0]),
524     make_hwstate(2.01, 0, 2, 2, &finger_states[2]),
525     make_hwstate(2.02, 0, 2, 2, &finger_states[4]),
526     make_hwstate(2.03, 0, 0, 0, nullptr),
527   };
528 
529   size_t idx = 0;
530 
531   // Consistent movement
532   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[idx++], nullptr));
533   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[idx++], nullptr));
534 
535   Gesture* gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
536   ASSERT_NE(nullptr, gs);
537   EXPECT_EQ(kGestureTypeMove, gs->type);
538 
539   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
540   ASSERT_NE(nullptr, gs);
541   EXPECT_EQ(kGestureTypeScroll, gs->type);
542 }
543 
544 // Tests that after a scroll is happening, if a finger lets go, scrolling stops.
TEST(ImmediateInterpreterTest,ScrollReevaluateTest)545 TEST(ImmediateInterpreterTest, ScrollReevaluateTest) {
546   ImmediateInterpreter ii(nullptr, nullptr);
547   HardwareProperties hwprops = {
548     .right = 100,
549     .bottom = 100,
550     .res_x = 1,
551     .res_y = 1,
552     .orientation_minimum = -1,
553     .orientation_maximum = 2,
554     .max_finger_cnt = 2,
555     .max_touch_cnt = 5,
556     .supports_t5r2 = 0,
557     .support_semi_mt = 0,
558     .is_button_pad = 1,
559     .has_wheel = 0,
560     .wheel_is_hi_res = 0,
561     .is_haptic_pad = 0,
562   };
563 
564   FingerState finger_states[] = {
565     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
566     // Consistent movement for 4 frames
567     {0, 0, 0, 0, 20, 0, 10, 95, 1, 0},
568     {0, 0, 0, 0, 20, 0, 59, 95, 2, 0},
569 
570     {0, 0, 0, 0, 20, 0, 10, 85, 1, 0},
571     {0, 0, 0, 0, 20, 0, 59, 85, 2, 0},
572 
573     {0, 0, 0, 0, 20, 0, 10, 75, 1, 0},
574     {0, 0, 0, 0, 20, 0, 59, 75, 2, 0},
575 
576     // Just too far apart to be scrolling
577     {0, 0, 0, 0, 20, 0, 10, 65, 1, 0},
578     {0, 0, 0, 0, 20, 0, 61, 65, 2, 0},
579   };
580   HardwareState hardware_states[] = {
581     // time, buttons, finger count, touch count, finger states pointer
582     make_hwstate(1.00, 0, 2, 2, &finger_states[0]),
583     make_hwstate(2.00, 0, 2, 2, &finger_states[0]),
584     make_hwstate(2.01, 0, 2, 2, &finger_states[2]),
585     make_hwstate(2.02, 0, 2, 2, &finger_states[4]),
586     make_hwstate(2.03, 0, 2, 2, &finger_states[6]),
587   };
588 
589   TestInterpreterWrapper wrapper(&ii, &hwprops);
590 
591   size_t idx = 0;
592 
593   // Consistent movement
594   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[idx++], nullptr));
595   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[idx++], nullptr));
596 
597   Gesture* gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
598   ASSERT_NE(nullptr, gs);
599   EXPECT_EQ(kGestureTypeScroll, gs->type);
600 
601   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
602   ASSERT_NE(nullptr, gs);
603   EXPECT_EQ(kGestureTypeScroll, gs->type);
604 
605   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
606   if (gs) {
607     fprintf(stderr, "gs:%si=%zd\n", gs->String().c_str(), idx);
608     EXPECT_NE(kGestureTypeScroll, gs->type);
609   }
610 }
611 
612 
613 // This is based on a log from Dave Moore. He put one finger down, which put
614 // it into move mode, then put a second finger down a bit later, but it was
615 // stuck in move mode. This tests that it does switch to scroll mode.
TEST(ImmediateInterpreterTest,OneFingerThenTwoDelayedStartScrollTest)616 TEST(ImmediateInterpreterTest, OneFingerThenTwoDelayedStartScrollTest) {
617   ImmediateInterpreter ii(nullptr, nullptr);
618   HardwareProperties hwprops = {
619     .right = 100,
620     .bottom = 100,
621     .res_x = 1,
622     .res_y = 1,
623     .orientation_minimum = -1,
624     .orientation_maximum = 2,
625     .max_finger_cnt = 2,
626     .max_touch_cnt = 5,
627     .supports_t5r2 = 0,
628     .support_semi_mt = 0,
629     .is_button_pad = 1,
630     .has_wheel = 0,
631     .wheel_is_hi_res = 0,
632     .is_haptic_pad = 0,
633   };
634 
635   FingerState finger_states[] = {
636     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
637     // Consistent movement for 4 frames
638     {0, 0, 0, 0, 20, 0, 40, 85, 2, 0},
639 
640     {0, 0, 0, 0, 20, 0, 40, 85, 1, 0},
641     {0, 0, 0, 0, 20, 0, 60, 83, 2, 0},
642 
643     {0, 0, 0, 0, 20, 0, 40, 77, 1, 0},
644     {0, 0, 0, 0, 20, 0, 60, 75, 2, 0},
645 
646   };
647   HardwareState hardware_states[] = {
648     // time, buttons, finger count, touch count, finger states pointer
649     make_hwstate(1.00, 0, 1, 1, &finger_states[0]),
650     make_hwstate(1.20, 0, 2, 2, &finger_states[1]),
651     make_hwstate(2.00, 0, 2, 2, &finger_states[1]),
652     make_hwstate(2.01, 0, 2, 2, &finger_states[3]),
653     make_hwstate(2.03, 0, 0, 0, nullptr),
654   };
655 
656   TestInterpreterWrapper wrapper(&ii, &hwprops);
657 
658   size_t idx = 0;
659 
660   // Consistent movement
661   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[idx++], nullptr));
662   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[idx++], nullptr));
663 
664   Gesture* gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
665   EXPECT_EQ(nullptr, gs);
666 
667   gs = wrapper.SyncInterpret(hardware_states[idx++], nullptr);
668   ASSERT_NE(nullptr, gs);
669   EXPECT_EQ(kGestureTypeScroll, gs->type);
670 }
671 
672 namespace {
673 
674 enum TestCaseStartOrContinueFlag {
675   kS,  // start
676   kC  // continue
677 };
678 
679 enum OneFatFingerScrollTestExpectation {
680   kAnything,
681   kScroll
682 };
683 
684 struct OneFatFingerScrollTestInputs {
685   TestCaseStartOrContinueFlag start;
686   stime_t now;
687   float x0, y0, p0, x1, y1, p1;  // (x, y) coordinate and pressure
688   OneFatFingerScrollTestExpectation expectation;
689 };
690 
691 }  // namespace {}
692 
693 // Tests two scroll operations with data from actual logs from Ryan Tabone.
TEST(ImmediateInterpreterTest,OneFatFingerScrollTest)694 TEST(ImmediateInterpreterTest, OneFatFingerScrollTest) {
695   std::unique_ptr<ImmediateInterpreter> ii;
696   HardwareProperties hwprops = {
697     .right = 106.666672,
698     .bottom = 68.000000,
699     .res_x = 1,
700     .res_y = 1,
701     .orientation_minimum = -1,
702     .orientation_maximum = 2,
703     .max_finger_cnt = 15,
704     .max_touch_cnt = 5,
705     .supports_t5r2 = 0,
706     .support_semi_mt = 0,
707     .is_button_pad = true,
708     .has_wheel = 0,
709     .wheel_is_hi_res = 0,
710     .is_haptic_pad = false,
711   };
712   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
713   // 4 runs that were failing, but now pass:
714   OneFatFingerScrollTestInputs inputs[] = {
715     { kS, 54.6787, 49.83, 33.20,  3.71, 73.25, 22.80, 32.82, kAnything },
716     { kC, 54.6904, 49.83, 33.20, 61.93, 73.25, 22.80, 40.58, kAnything },
717     { kC, 54.7022, 49.83, 33.20, 67.75, 73.25, 22.90, 40.58, kAnything },
718     { kC, 54.7140, 49.83, 33.20, 67.75, 73.25, 22.90, 42.52, kAnything },
719     { kC, 54.7256, 49.66, 33.20, 71.63, 73.25, 21.90, 38.64, kAnything },
720     { kC, 54.7373, 49.00, 32.90, 75.51, 72.91, 20.80, 40.58, kAnything },
721     { kC, 54.7492, 48.50, 31.70, 77.45, 72.75, 19.90, 40.58, kScroll },
722     { kC, 54.7613, 47.91, 30.30, 77.45, 73.08, 17.90, 44.46, kScroll },
723     { kC, 54.7734, 47.58, 26.80, 79.39, 73.08, 16.10, 46.40, kScroll },
724     { kC, 54.7855, 47.33, 24.30, 85.21, 73.08, 13.40, 42.52, kScroll },
725     { kC, 54.7976, 47.08, 21.30, 83.27, 73.25, 11.00, 46.40, kScroll },
726     { kC, 54.8099, 47.08, 18.30, 87.15, 73.16,  9.00, 44.46, kScroll },
727     { kC, 54.8222, 46.75, 15.90, 83.27, 73.16,  6.80, 42.52, kScroll },
728     { kC, 54.8344, 46.66, 13.50, 85.21, 73.33,  4.80, 46.40, kScroll },
729     { kC, 54.8469, 46.50, 11.80, 83.27, 73.33,  3.70, 44.46, kScroll },
730     { kC, 54.8598, 46.41, 10.80, 85.21, 73.33,  3.00, 46.40, kScroll },
731     { kC, 54.8726, 46.00,  9.50, 79.39, 73.33,  1.70, 40.58, kScroll },
732     { kC, 54.8851, 46.00,  8.60, 81.33, 73.33,  1.50, 40.58, kScroll },
733     { kC, 54.8975, 46.00,  7.90, 83.27, 73.33,  1.20, 38.64, kScroll },
734     { kC, 54.9099, 46.00,  7.20, 85.21, 73.33,  1.20, 38.64, kScroll },
735     { kC, 54.9224, 46.00,  7.00, 81.33, 73.33,  1.00, 34.76, kScroll },
736     { kC, 54.9350, 46.00,  7.00, 81.33, 73.66,  0.90, 34.76, kScroll },
737     { kC, 54.9473, 46.00,  6.80, 83.27, 73.66,  0.50, 34.76, kScroll },
738     { kC, 54.9597, 46.00,  6.70, 77.45, 73.66,  0.40, 32.82, kScroll },
739     { kC, 54.9721, 46.00,  6.60, 56.10, 73.50,  0.40, 28.94, kScroll },
740     { kC, 54.9844, 46.41,  6.20, 32.82, 73.16,  0.40, 19.24, kScroll },
741     { kC, 54.9967, 46.08,  6.20, 17.30, 72.41,  0.40,  7.60, kScroll },
742     { kC, 55.0067, 47.16,  6.30,  3.71,  0.00,  0.00,  0.00, kAnything },
743 
744     { kS, 91.6606, 48.08, 31.20,  9.54,  0.00,  0.00,  0.00, kAnything },
745     { kC, 91.6701, 48.08, 31.20, 23.12,  0.00,  0.00,  0.00, kAnything },
746     { kC, 91.6821, 48.25, 31.20, 38.64, 69.50, 23.20,  7.60, kAnything },
747     { kC, 91.6943, 48.25, 31.20, 50.28, 69.50, 23.20, 19.24, kAnything },
748     { kC, 91.7062, 48.25, 31.20, 58.04, 69.41, 23.00, 23.12, kAnything },
749     { kC, 91.7182, 48.25, 31.20, 63.87, 69.41, 23.00, 27.00, kAnything },
750     { kC, 91.7303, 48.25, 31.20, 65.81, 69.16, 23.00, 30.88, kAnything },
751     { kC, 91.7423, 48.25, 31.20, 65.81, 69.08, 23.00, 30.88, kAnything },
752     { kC, 91.7541, 48.25, 31.20, 67.75, 69.83, 21.90, 25.06, kAnything },
753     { kC, 91.7660, 48.25, 30.80, 67.75, 69.75, 21.90, 27.00, kAnything },
754     { kC, 91.7778, 48.25, 30.00, 63.87, 69.75, 21.60, 30.88, kAnything },
755     { kC, 91.7895, 48.25, 29.00, 63.87, 69.75, 21.30, 30.88, kAnything },
756     { kC, 91.8016, 48.25, 27.60, 65.81, 69.50, 19.90, 34.76, kAnything },
757     { kC, 91.8138, 48.16, 26.00, 67.75, 69.41, 18.70, 36.70, kScroll },
758     { kC, 91.8259, 47.83, 24.30, 69.69, 69.16, 17.50, 40.58, kScroll },
759     { kC, 91.8382, 47.66, 22.50, 69.69, 69.16, 15.50, 36.70, kScroll },
760     { kC, 91.8503, 47.58, 19.20, 71.63, 69.16, 13.20, 34.76, kScroll },
761     { kC, 91.8630, 47.41, 17.10, 71.63, 69.16, 10.80, 40.58, kScroll },
762     { kC, 91.8751, 47.16, 14.70, 73.57, 69.16,  8.40, 34.76, kScroll },
763     { kC, 91.8871, 47.16, 12.70, 73.57, 69.50,  7.10, 36.70, kScroll },
764     { kC, 91.8994, 47.16, 11.30, 71.63, 69.75,  5.90, 36.70, kScroll },
765     { kC, 91.9119, 47.16, 10.10, 67.75, 69.75,  4.40, 40.58, kScroll },
766     { kC, 91.9243, 47.58,  8.70, 69.69, 69.75,  3.50, 42.52, kScroll },
767     { kC, 91.9367, 48.00,  7.80, 63.87, 70.08,  2.70, 38.64, kScroll },
768     { kC, 91.9491, 48.33,  6.90, 59.99, 70.58,  2.10, 34.76, kScroll },
769     { kC, 91.9613, 48.66,  6.50, 56.10, 70.58,  1.50, 32.82, kScroll },
770     { kC, 91.9732, 48.91,  6.00, 48.34, 70.66,  1.10, 28.94, kScroll },
771     { kC, 91.9854, 49.00,  5.90, 38.64, 71.00,  1.10, 23.12, kScroll },
772     { kC, 91.9975, 49.41,  5.60, 27.00, 71.33,  1.10, 15.36, kScroll },
773     { kC, 92.0094, 49.41,  5.30, 13.42, 71.33,  0.90,  9.54, kScroll },
774     { kC, 92.0215, 49.33,  4.20,  7.60, 71.33,  0.50,  3.71, kScroll },
775 
776     { kS, 93.3635, 43.58, 31.40, 36.70, 60.75, 19.00, 11.48, kAnything },
777     { kC, 93.3757, 43.58, 31.40, 73.57, 60.58, 18.80, 27.00, kAnything },
778     { kC, 93.3880, 43.58, 31.40, 75.51, 60.41, 17.90, 32.82, kAnything },
779     { kC, 93.4004, 43.33, 31.20, 77.45, 60.33, 17.40, 38.64, kAnything },
780     { kC, 93.4126, 43.00, 30.70, 79.39, 60.33, 16.50, 42.52, kAnything },
781     { kC, 93.4245, 42.75, 28.90, 81.33, 60.33, 15.70, 46.40, kScroll },
782     { kC, 93.4364, 42.41, 27.00, 79.39, 60.33, 14.30, 48.34, kScroll },
783     { kC, 93.4485, 42.16, 25.80, 87.15, 60.33, 12.50, 50.28, kScroll },
784     { kC, 93.4609, 42.08, 24.20, 89.09, 60.33, 11.10, 56.10, kScroll },
785     { kC, 93.4733, 41.66, 21.70, 81.33, 60.33,  9.70, 52.22, kScroll },
786     { kC, 93.4855, 41.66, 18.50, 85.21, 60.33,  7.80, 52.22, kScroll },
787     { kC, 93.4978, 41.66, 16.29, 85.21, 60.66,  5.40, 54.16, kScroll },
788     { kC, 93.5104, 41.66, 13.20, 79.39, 60.75,  3.80, 54.16, kScroll },
789     { kC, 93.5227, 41.66, 11.80, 79.39, 62.33,  2.00, 42.52, kScroll },
790     { kC, 93.5350, 41.91, 10.60, 71.63, 61.58,  1.80, 42.52, kScroll },
791     { kC, 93.5476, 42.00,  9.10, 67.75, 61.83,  1.20, 38.64, kScroll },
792     { kC, 93.5597, 42.41,  7.70, 58.04, 61.83,  0.80, 32.82, kScroll },
793     { kC, 93.5718, 42.41,  7.20, 48.34, 61.83,  0.80, 27.00, kScroll },
794     { kC, 93.5837, 42.33,  6.80, 34.76, 62.08,  0.50, 19.24, kScroll },
795     { kC, 93.5957, 42.00,  6.10, 19.24, 62.08,  0.50, 15.36, kScroll },
796     { kC, 93.6078, 41.91,  6.30,  7.60, 62.08,  0.50,  5.65, kAnything },
797 
798     { kS, 95.4803, 65.66, 34.90, 13.42,  0.00,  0.00,  0.00, kAnything },
799     { kC, 95.4901, 66.00, 35.00, 36.70,  0.00,  0.00,  0.00, kAnything },
800     { kC, 95.5024, 66.00, 35.10, 40.58, 44.66, 45.29, 59.99, kAnything },
801     { kC, 95.5144, 66.00, 35.40, 38.64, 44.66, 45.29, 81.33, kAnything },
802     { kC, 95.5267, 66.00, 35.40, 38.64, 44.50, 45.29, 87.15, kAnything },
803     { kC, 95.5388, 66.00, 35.40, 40.58, 44.50, 45.29, 87.15, kAnything },
804     { kC, 95.5507, 66.00, 33.60, 38.64, 44.50, 45.29, 91.03, kAnything },
805     { kC, 95.5625, 65.75, 32.00, 34.76, 44.08, 43.60, 91.03, kScroll },
806     { kC, 95.5747, 66.75, 30.00, 42.52, 43.83, 42.00, 89.09, kScroll },
807     { kC, 95.5866, 66.75, 27.50, 38.64, 43.58, 38.90, 87.15, kScroll },
808     { kC, 95.5986, 66.75, 25.00, 44.46, 43.58, 36.50, 92.97, kScroll },
809     { kC, 95.6111, 66.75, 22.70, 42.52, 43.33, 33.70, 89.09, kScroll },
810     { kC, 95.6230, 67.16, 20.40, 42.52, 43.33, 31.30, 94.91, kScroll },
811     { kC, 95.6351, 67.33, 18.70, 44.46, 43.33, 28.90, 96.85, kScroll },
812     { kC, 95.6476, 67.50, 17.30, 48.34, 43.33, 26.10, 92.97, kScroll },
813     { kC, 95.6596, 67.83, 16.20, 46.40, 43.33, 25.00, 92.97, kScroll },
814     { kC, 95.6717, 67.83, 15.60, 42.52, 43.33, 24.20, 94.91, kScroll },
815     { kC, 95.6837, 68.00, 13.80, 46.40, 43.33, 23.90, 92.97, kScroll },
816     { kC, 95.6959, 68.00, 13.80, 44.46, 43.33, 23.70, 92.97, kScroll },
817     { kC, 95.7080, 68.00, 13.80, 44.46, 43.33, 23.50, 94.91, kScroll },
818     { kC, 95.7199, 68.00, 13.60, 44.46, 43.33, 23.10, 96.85, kScroll },
819     { kC, 95.7321, 68.00, 13.60, 44.46, 43.33, 23.00, 98.79, kScroll },
820     { kC, 95.7443, 68.25, 13.60, 44.46, 43.25, 23.00, 98.79, kScroll },
821   };
822   for (size_t i = 0; i < arraysize(inputs); i++) {
823     if (inputs[i].start == kS) {
824       ii.reset(new ImmediateInterpreter(nullptr, nullptr));
825       wrapper.Reset(ii.get());
826     }
827 
828     FingerState fs[] = {
829       { 0, 0, 0, 0, inputs[i].p0, 0.0, inputs[i].x0, inputs[i].y0, 1, 0 },
830       { 0, 0, 0, 0, inputs[i].p1, 0.0, inputs[i].x1, inputs[i].y1, 2, 0 },
831     };
832     unsigned short finger_cnt = inputs[i].p1 == 0.0 ? 1 : 2;
833     HardwareState hs =
834         make_hwstate(inputs[i].now, 0, finger_cnt, finger_cnt, fs);
835 
836     stime_t timeout = NO_DEADLINE;
837     Gesture* gs = wrapper.SyncInterpret(hs, &timeout);
838     switch (inputs[i].expectation) {
839       case kAnything:
840         // Anything goes
841         break;
842       case kScroll:
843         EXPECT_NE(nullptr, gs) << "i=" << i;
844         if (!gs)
845           break;
846         EXPECT_EQ(kGestureTypeScroll, gs->type);
847         break;
848     }
849   }
850 };
851 
852 struct NoLiftoffScrollTestInputs {
853   bool reset;
854   stime_t now;
855   float x0, y0, p0, x1, y1, p1;  // (x, y) coordinate and pressure per finger
856 };
857 
858 // Tests that if one scrolls backwards a bit before lifting fingers off, we
859 // don't scroll backwards. Based on an actual log
TEST(ImmediateInterpreterTest,NoLiftoffScrollTest)860 TEST(ImmediateInterpreterTest, NoLiftoffScrollTest) {
861   std::unique_ptr<ImmediateInterpreter> ii;
862   HardwareProperties hwprops = {
863     .right = 106.666672,
864     .bottom = 68.000000,
865     .res_x = 1,
866     .res_y = 1,
867     .orientation_minimum = -1,
868     .orientation_maximum = 2,
869     .max_finger_cnt = 15,
870     .max_touch_cnt = 5,
871     .supports_t5r2 = 0,
872     .support_semi_mt = 0,
873     .is_button_pad = true,
874     .has_wheel = 0,
875     .wheel_is_hi_res = 0,
876     .is_haptic_pad = false,
877   };
878   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
879 
880   NoLiftoffScrollTestInputs inputs[] = {
881     // These logs are examples of scrolling up that may have some accidental
882     // reverse-scroll when fingers lift-off
883     {  true, 4.9621, 59.5, 55.9, 17.30, 43.2, 62.5, 19.24 },
884     { false, 4.9745, 59.5, 55.9, 30.88, 43.2, 62.5, 25.06 },
885     { false, 4.9862, 59.3, 55.9, 34.76, 43.3, 61.7, 28.94 },
886     { false, 4.9974, 59.3, 55.4, 36.70, 43.0, 60.7, 32.82 },
887     { false, 5.0085, 59.0, 54.4, 40.58, 43.0, 58.7, 36.70 },
888     { false, 5.0194, 59.0, 50.9, 44.46, 42.5, 55.7, 42.52 },
889     { false, 5.0299, 59.0, 48.2, 46.40, 42.2, 52.7, 44.46 },
890     { false, 5.0412, 58.7, 44.5, 46.40, 41.6, 49.7, 48.34 },
891     { false, 5.0518, 57.3, 39.6, 48.34, 41.2, 45.7, 54.16 },
892     { false, 5.0626, 57.1, 35.2, 48.34, 41.0, 42.0, 61.93 },
893     { false, 5.0739, 56.7, 30.8, 56.10, 41.1, 36.6, 69.69 },
894     { false, 5.0848, 56.3, 26.4, 58.04, 39.7, 32.3, 63.87 },
895     { false, 5.0957, 56.3, 23.4, 61.93, 39.7, 27.8, 67.75 },
896     { false, 5.1068, 56.3, 19.9, 67.75, 39.7, 24.1, 71.63 },
897     { false, 5.1177, 56.7, 18.1, 71.63, 39.7, 20.4, 75.51 },
898     { false, 5.1287, 57.1, 15.9, 71.63, 39.7, 18.7, 75.51 },
899     { false, 5.1398, 57.5, 14.2, 77.45, 39.7, 17.3, 79.39 },
900     { false, 5.1508, 57.6, 13.3, 75.51, 39.7, 16.1, 77.45 },
901     { false, 5.1619, 57.7, 12.9, 79.39, 40.0, 15.5, 83.27 },
902     { false, 5.1734, 58.1, 12.8, 79.39, 40.0, 15.4, 83.27 },
903     { false, 5.1847, 58.1, 12.7, 79.39, 40.0, 15.3, 83.27 },
904     { false, 5.1963, 58.1, 12.7, 78.42, 40.0, 15.3, 83.27 },
905     { false, 5.2078, 58.1, 12.7, 77.45, 40.0, 15.3, 83.27 },
906     { false, 5.2191, 58.1, 12.7, 79.39, 40.0, 15.3, 83.27 },
907     { false, 5.2306, 58.1, 12.7, 78.42, 40.0, 15.3, 82.30 },
908     { false, 5.2421, 58.1, 12.7, 77.45, 40.0, 15.3, 81.33 },
909     { false, 5.2533, 58.1, 12.7, 77.45, 40.0, 15.3, 77.45 },
910     { false, 5.2642, 58.1, 12.7, 63.87, 40.0, 15.4, 58.04 },
911     { false, 5.2752, 57.9, 12.7, 34.76, 40.0, 15.8, 25.06 },
912 
913     {  true, 4.1501, 66.25, 19.10, 46.40, 83.50, 15.10, 46.40 },
914     { false, 4.1610, 66.25, 19.00, 48.34, 83.58, 15.10, 46.40 },
915     { false, 4.1721, 66.58, 18.50, 48.34, 83.58, 15.00, 44.46 },
916     { false, 4.1830, 67.00, 18.50, 48.34, 83.66, 14.90, 44.46 },
917     { false, 4.1943, 67.08, 18.40, 50.28, 83.66, 14.80, 46.40 },
918     { false, 4.2053, 67.08, 18.40, 50.28, 83.66, 14.80, 46.40 },
919     { false, 4.2163, 67.08, 18.40, 50.28, 83.66, 14.80, 46.40 },
920     { false, 4.2274, 67.08, 18.40, 48.34, 83.66, 14.80, 46.40 },
921     { false, 4.2385, 67.08, 18.30, 50.28, 83.83, 14.60, 46.40 },
922     { false, 4.2494, 67.08, 18.10, 48.34, 83.91, 14.30, 46.40 },
923     { false, 4.2602, 67.08, 17.60, 46.40, 84.08, 14.10, 44.46 },
924     { false, 4.2712, 67.08, 17.40, 48.34, 84.25, 13.70, 46.40 },
925     { false, 4.2822, 67.25, 17.20, 48.34, 84.50, 13.40, 48.34 },
926     { false, 4.2932, 67.33, 16.90, 46.40, 84.75, 13.20, 46.40 },
927     { false, 4.3044, 67.33, 16.60, 46.40, 84.91, 13.00, 48.34 },
928     { false, 4.3153, 67.41, 16.50, 46.40, 84.91, 12.90, 46.40 },
929     { false, 4.3264, 67.50, 16.29, 46.40, 84.91, 12.90, 46.40 },
930     { false, 4.3372, 67.58, 16.29, 46.40, 85.08, 12.90, 48.34 },
931     { false, 4.3481, 67.58, 16.10, 44.46, 85.08, 12.90, 48.34 },
932     { false, 4.3591, 67.58, 16.00, 44.46, 85.08, 12.90, 48.34 },
933     { false, 4.3699, 67.58, 15.95, 44.46, 85.08, 12.85, 48.34 },
934     { false, 4.3808, 67.58, 15.90, 44.46, 85.08, 12.80, 48.34 },
935     { false, 4.3922, 67.58, 15.90, 44.46, 85.25, 12.50, 48.34 },
936     { false, 4.4035, 67.75, 15.80, 46.40, 85.25, 12.40, 46.40 },
937     { false, 4.4146, 67.75, 15.30, 46.40, 85.33, 12.20, 48.34 },
938     { false, 4.4260, 67.91, 15.20, 48.34, 85.75, 12.20, 50.28 },
939     { false, 4.4373, 67.91, 15.20, 46.40, 85.75, 12.10, 48.34 },
940     { false, 4.4485, 67.91, 15.10, 46.40, 85.75, 12.10, 48.34 },
941     { false, 4.4712, 67.91, 15.05, 46.40, 85.75, 12.05, 48.34 },
942     { false, 4.4940, 67.91, 15.00, 46.40, 85.75, 12.00, 48.34 },
943     { false, 4.5052, 67.91, 14.80, 48.34, 85.75, 11.80, 48.34 },
944     { false, 4.5163, 68.00, 14.60, 48.34, 85.83, 11.70, 48.34 },
945     { false, 4.5276, 68.08, 14.50, 48.34, 85.91, 11.60, 50.28 },
946     { false, 4.5390, 68.08, 14.30, 46.40, 85.91, 11.50, 48.34 },
947     { false, 4.5499, 68.08, 14.30, 48.34, 85.91, 11.50, 48.34 },
948     { false, 4.5613, 68.08, 14.30, 47.37, 85.91, 11.45, 48.34 },
949     { false, 4.5726, 68.08, 14.30, 46.40, 85.91, 11.40, 48.34 },
950     { false, 4.5837, 68.08, 14.20, 46.40, 85.91, 11.40, 48.34 },
951     { false, 4.5949, 68.08, 14.10, 46.40, 85.91, 11.40, 48.34 },
952     { false, 4.6061, 68.16, 14.10, 46.40, 85.91, 11.40, 48.34 },
953     { false, 4.6172, 68.16, 14.00, 48.34, 86.00, 11.30, 48.34 },
954     { false, 4.6285, 68.25, 13.90, 48.34, 86.00, 11.20, 48.34 },
955     { false, 4.6399, 68.25, 13.90, 48.34, 86.00, 11.20, 48.34 },
956     { false, 4.6514, 68.33, 13.80, 48.34, 86.00, 11.10, 48.34 },
957     { false, 4.6741, 68.33, 13.80, 47.37, 86.00, 11.05, 47.37 },
958     { false, 4.6968, 68.33, 13.80, 46.40, 86.00, 11.00, 46.40 },
959     { false, 4.7079, 68.33, 13.80, 42.52, 86.00, 11.00, 44.46 },
960     { false, 4.7191, 68.33, 13.80, 38.64, 86.00, 11.00, 42.52 },
961     { false, 4.7304, 68.33, 13.80, 34.76, 86.00, 11.00, 42.52 },
962     { false, 4.7417, 68.41, 13.80, 27.00, 86.41, 11.00, 36.70 },
963     { false, 4.7528, 68.83, 13.60, 21.18, 86.25, 10.90, 32.82 },
964     { false, 4.7638, 68.83, 13.60, 13.42, 86.25, 10.80, 25.06 },
965     { false, 4.7749, 68.83, 13.60,  5.65, 86.25, 10.50, 15.36 },
966     { false, 4.7862, 68.75, 14.00,  1.77, 85.91, 10.50,  7.60 },
967   };
968   for (size_t i = 0; i < arraysize(inputs); i++) {
969     if (inputs[i].reset) {
970       ii.reset(new ImmediateInterpreter(nullptr, nullptr));
971       wrapper.Reset(ii.get());
972     }
973     FingerState fs[] = {
974       { 0, 0, 0, 0, inputs[i].p0, 0.0, inputs[i].x0, inputs[i].y0, 1, 0 },
975       { 0, 0, 0, 0, inputs[i].p1, 0.0, inputs[i].x1, inputs[i].y1, 2, 0 },
976     };
977     HardwareState hs = make_hwstate(inputs[i].now, 0, 2, 2, fs);
978 
979     stime_t timeout = NO_DEADLINE;
980     Gesture* gs = wrapper.SyncInterpret(hs, &timeout);
981     if (gs) {
982       EXPECT_EQ(kGestureTypeScroll, gs->type);
983       EXPECT_LE(gs->details.scroll.dy, 0.0);
984     }
985   }
986 }
987 
988 struct HardwareStateAnScrollExpectations {
989   HardwareState hs;
990   float dx;
991   float dy;
992 };
993 
TEST(ImmediateInterpreterTest,DiagonalSnapTest)994 TEST(ImmediateInterpreterTest, DiagonalSnapTest) {
995   std::unique_ptr<ImmediateInterpreter> ii;
996   HardwareProperties hwprops = {
997     .right = 100,
998     .bottom = 100,
999     .res_x = 1,
1000     .res_y = 1,
1001     .orientation_minimum = -1,
1002     .orientation_maximum = 2,
1003     .max_finger_cnt = 2,
1004     .max_touch_cnt = 5,
1005     .supports_t5r2 = 0,
1006     .support_semi_mt = 0,
1007     .is_button_pad = 1,
1008     .has_wheel = 0,
1009     .wheel_is_hi_res = 0,
1010     .is_haptic_pad = 0,
1011   };
1012   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
1013 
1014   const float kBig = 5;  // mm
1015   const float kSml = 1;  // mm
1016 
1017   const float kX0 = 40;
1018   const float kX1 = 60;
1019   const float kY = 50;  // heh
1020 
1021   short fid = 1;
1022 
1023   FingerState finger_states[] = {
1024     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1025 
1026     // Perfect diagonal movement - should scroll diagonally
1027     {0, 0, 0, 0, 50, 0, kX0, kY, fid++, 0},
1028     {0, 0, 0, 0, 50, 0, kX1, kY, fid--, 0},
1029 
1030     {0, 0, 0, 0, 50, 0, kX0 + kBig, kY + kBig, fid++, 0},
1031     {0, 0, 0, 0, 50, 0, kX1 + kBig, kY + kBig, fid++, 0},
1032 
1033     // Almost vertical movement - should snap to vertical
1034     {0, 0, 0, 0, 50, 0, kX0, kY, fid++, 0},
1035     {0, 0, 0, 0, 50, 0, kX1, kY, fid--, 0},
1036 
1037     {0, 0, 0, 0, 50, 0, kX0 + kSml, kY + kBig, fid++, 0},
1038     {0, 0, 0, 0, 50, 0, kX1 + kSml, kY + kBig, fid++, 0},
1039 
1040     // Almost horizontal movement - should snap to horizontal
1041     {0, 0, 0, 0, 50, 0, kX0, kY, fid++, 0},
1042     {0, 0, 0, 0, 50, 0, kX1, kY, fid--, 0},
1043 
1044     {0, 0, 0, 0, 50, 0, kX0 + kBig, kY + kSml, fid++, 0},
1045     {0, 0, 0, 0, 50, 0, kX1 + kBig, kY + kSml, fid++, 0},
1046 
1047     // Vertical movement with Warp - shouldn't scroll
1048     {0, 0, 0, 0, 50, 0, kX0, kY, fid++, 0},
1049     {0, 0, 0, 0, 50, 0, kX1, kY, fid--, 0},
1050 
1051     {0, 0, 0, 0, 50, 0, kX0, kY + kBig, fid++, GESTURES_FINGER_WARP_Y},
1052     {0, 0, 0, 0, 50, 0, kX1, kY + kBig, fid++, GESTURES_FINGER_WARP_Y},
1053   };
1054   ssize_t idx = 0;
1055   HardwareStateAnScrollExpectations hardware_states[] = {
1056     // time, buttons, finger count, touch count, finger states pointer
1057     { make_hwstate(0.000, 0, 2, 2, &finger_states[idx * 4 ]),
1058       0, 0 },
1059     { make_hwstate(1.000, 0, 2, 2, &finger_states[idx * 4 ]),
1060       0, 0 },
1061     { make_hwstate(1.010, 0, 2, 2, &finger_states[idx++ * 4 + 2]),
1062       kBig, kBig },
1063 
1064     { make_hwstate(0.000, 0, 2, 2, &finger_states[idx * 4 ]),
1065       0, 0 },
1066     { make_hwstate(1.000, 0, 2, 2, &finger_states[idx * 4 ]),
1067       0, 0 },
1068     { make_hwstate(1.010, 0, 2, 2, &finger_states[idx++ * 4 + 2]),
1069       0, kBig },
1070 
1071     { make_hwstate(0.000, 0, 2, 2, &finger_states[idx * 4 ]),
1072       0, 0 },
1073     { make_hwstate(1.000, 0, 2, 2, &finger_states[idx * 4 ]),
1074       0, 0 },
1075     { make_hwstate(1.010, 0, 2, 2, &finger_states[idx++ * 4 + 2]),
1076       kBig, 0 },
1077 
1078     { make_hwstate(0.000, 0, 2, 2, &finger_states[idx * 4 ]),
1079       0, 0 },
1080     { make_hwstate(1.000, 0, 2, 2, &finger_states[idx * 4 ]),
1081       0, 0 },
1082     { make_hwstate(1.010, 0, 2, 2, &finger_states[idx++ * 4 + 2]),
1083       0, 0 },
1084   };
1085 
1086   for (size_t i = 0; i < arraysize(hardware_states); i++) {
1087     HardwareStateAnScrollExpectations& hse = hardware_states[i];
1088     if (hse.hs.timestamp == 0.0) {
1089       ii.reset(new ImmediateInterpreter(nullptr, nullptr));
1090       wrapper.Reset(ii.get());
1091     }
1092     Gesture* gs = wrapper.SyncInterpret(hse.hs, nullptr);
1093     if (hse.dx == 0.0 && hse.dy == 0.0) {
1094       EXPECT_EQ(nullptr, gs);
1095       continue;
1096     }
1097     ASSERT_NE(nullptr, gs);
1098     EXPECT_EQ(kGestureTypeScroll, gs->type);
1099     EXPECT_FLOAT_EQ(hse.dx, gs->details.scroll.dx);
1100     EXPECT_FLOAT_EQ(hse.dy, gs->details.scroll.dy);
1101   }
1102 }
1103 
TEST(ImmediateInterpreterTest,RestingFingerTest)1104 TEST(ImmediateInterpreterTest, RestingFingerTest) {
1105   std::unique_ptr<ImmediateInterpreter> ii;
1106   HardwareProperties hwprops = {
1107     .right = 100,
1108     .bottom = 100,
1109     .res_x = 1,
1110     .res_y = 1,
1111     .orientation_minimum = -1,
1112     .orientation_maximum = 2,
1113     .max_finger_cnt = 2,
1114     .max_touch_cnt = 5,
1115     .supports_t5r2 = 0,
1116     .support_semi_mt = 0,
1117     .is_button_pad = 1,
1118     .has_wheel = 0,
1119     .wheel_is_hi_res = 0,
1120     .is_haptic_pad = 0,
1121   };
1122   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
1123 
1124   const float kX = 7;
1125   float dx = 7;
1126   const float kRestY = hwprops.bottom - 7;
1127   const float kMoveY = kRestY - 10;
1128 
1129   const float kTO = 1.0;  // time to wait for change timeout
1130 
1131   FingerState finger_states[] = {
1132     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1133 
1134     // Resting finger in lower left
1135     {0, 0, 0, 0, 50, 0, kX, kRestY, 1, 0},
1136     // Moving finger
1137     {0, 0, 0, 0, 50, 0, kX, kMoveY, 2, 0},
1138   };
1139 
1140   // Left to right movement, then right to left
1141   for (size_t direction = 0; direction < 2; direction++) {
1142     if (direction == 1)
1143       dx *= -1.0;
1144     ii.reset(new ImmediateInterpreter(nullptr, nullptr));
1145     wrapper.Reset(ii.get());
1146     for (size_t i = 0; i < 4; i++) {
1147       HardwareState hs = make_hwstate(kTO + 0.01 * i, 0, 2, 2, finger_states);
1148       if (i == 0) {
1149         hs.timestamp -= kTO;
1150         Gesture* gs = wrapper.SyncInterpret(hs, nullptr);
1151         EXPECT_EQ(nullptr, gs);
1152         hs.timestamp += kTO;
1153         gs = wrapper.SyncInterpret(hs, nullptr);
1154         if (gs && gs->type == kGestureTypeMove) {
1155           EXPECT_FLOAT_EQ(0.0, gs->details.move.dx);
1156           EXPECT_FLOAT_EQ(0.0, gs->details.move.dy);
1157         }
1158       } else {
1159         Gesture* gs = wrapper.SyncInterpret(hs, nullptr);
1160         ASSERT_NE(nullptr, gs);
1161         EXPECT_EQ(kGestureTypeMove, gs->type);
1162         EXPECT_FLOAT_EQ(dx, gs->details.move.dx);
1163         EXPECT_FLOAT_EQ(0.0, gs->details.move.dy);
1164       }
1165       finger_states[1].position_x += dx;
1166     }
1167   }
1168 }
1169 
TEST(ImmediateInterpreterTest,ThumbRetainTest)1170 TEST(ImmediateInterpreterTest, ThumbRetainTest) {
1171   ImmediateInterpreter ii(nullptr, nullptr);
1172   HardwareProperties hwprops = {
1173     .right = 100,
1174     .bottom = 100,
1175     .res_x = 1,
1176     .res_y = 1,
1177     .orientation_minimum = -1,
1178     .orientation_maximum = 2,
1179     .max_finger_cnt = 2,
1180     .max_touch_cnt = 5,
1181     .supports_t5r2 = 0,
1182     .support_semi_mt = 0,
1183     .is_button_pad = 1,
1184     .has_wheel = 0,
1185     .wheel_is_hi_res = 0,
1186     .is_haptic_pad = 0,
1187   };
1188 
1189   FingerState finger_states[] = {
1190     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1191     // id 1 = finger, 2 = thumb
1192     {0, 0, 0, 0, 24, 0, 30, 30, 1, 0},
1193     {0, 0, 0, 0, 58, 0, 30, 50, 2, 0},
1194 
1195     // thumb, post-move
1196     {0, 0, 0, 0, 58, 0, 50, 50, 2, 0},
1197   };
1198   HardwareState hardware_states[] = {
1199     // time, buttons, finger count, touch count, finger states pointer
1200     make_hwstate(0.000, 0, 2, 2, &finger_states[0]),
1201     make_hwstate(0.100, 0, 2, 2, &finger_states[0]),
1202     make_hwstate(0.110, 0, 1, 1, &finger_states[1]),  // finger goes away
1203     make_hwstate(0.210, 0, 1, 1, &finger_states[1]),
1204     make_hwstate(0.220, 0, 1, 1, &finger_states[2]),  // thumb moves
1205   };
1206 
1207   TestInterpreterWrapper wrapper(&ii, &hwprops);
1208   ii.tap_enable_.val_ = 0;
1209 
1210   for (size_t i = 0; i < arraysize(hardware_states); i++) {
1211     Gesture* gs = wrapper.SyncInterpret(hardware_states[i], nullptr);
1212     if (!gs)
1213       continue;
1214     EXPECT_EQ(kGestureTypeMove, gs->type) << "i=" << i;
1215     EXPECT_FLOAT_EQ(0.0, gs->details.move.dx) << "i=" << i;
1216     EXPECT_FLOAT_EQ(0.0, gs->details.move.dy) << "i=" << i;
1217   }
1218 }
1219 
TEST(ImmediateInterpreterTest,ThumbRetainReevaluateTest)1220 TEST(ImmediateInterpreterTest, ThumbRetainReevaluateTest) {
1221   ImmediateInterpreter ii(nullptr, nullptr);
1222   HardwareProperties hwprops = {
1223     .right = 100,
1224     .bottom = 100,
1225     .res_x = 1,
1226     .res_y = 1,
1227     .orientation_minimum = -1,
1228     .orientation_maximum = 2,
1229     .max_finger_cnt = 2,
1230     .max_touch_cnt = 5,
1231     .supports_t5r2 = 0,
1232     .support_semi_mt = 0,
1233     .is_button_pad = 1,
1234     .has_wheel = 0,
1235     .wheel_is_hi_res = 0,
1236     .is_haptic_pad = 0,
1237   };
1238 
1239   FingerState finger_states[] = {
1240     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1241     // one thumb, one finger (it seems)
1242     {0, 0, 0, 0, 24, 0, 3.0, 3, 3, 0},
1243     {0, 0, 0, 0, 58, 0, 13.5, 3, 4, 0},
1244     // two big fingers, it turns out!
1245     {0, 0, 0, 0, 27, 0, 3.0, 6, 3, 0},
1246     {0, 0, 0, 0, 58, 0, 13.5, 6, 4, 0},
1247     // they  move
1248     {0, 0, 0, 0, 27, 0, 3.0, 7, 3, 0},
1249     {0, 0, 0, 0, 58, 0, 13.5, 7, 4, 0},
1250   };
1251   HardwareState hardware_states[] = {
1252     // time, buttons, finger count, touch count, finger states pointer
1253     make_hwstate(1.000, 0, 2, 2, &finger_states[0]),  // 2 fingers arrive
1254     make_hwstate(1.010, 0, 2, 2, &finger_states[2]),  // pressures fix
1255     make_hwstate(1.100, 0, 2, 2, &finger_states[4]),  // they move
1256   };
1257 
1258   TestInterpreterWrapper wrapper(&ii, &hwprops);
1259   ii.tap_enable_.val_ = 0;
1260 
1261   for (size_t i = 0; i < arraysize(hardware_states); i++) {
1262     Gesture* gs = wrapper.SyncInterpret(hardware_states[i], nullptr);
1263     EXPECT_TRUE(!gs || gs->type == kGestureTypeScroll);
1264   }
1265 }
1266 
TEST(ImmediateInterpreterTest,SetHardwarePropertiesTwiceTest)1267 TEST(ImmediateInterpreterTest, SetHardwarePropertiesTwiceTest) {
1268   ImmediateInterpreter ii(nullptr, nullptr);
1269   HardwareProperties hwprops = {
1270     .right = 1000,
1271     .bottom = 1000,
1272     .res_x = 500,
1273     .res_y = 500,
1274     .orientation_minimum = -1,
1275     .orientation_maximum = 2,
1276     .max_finger_cnt = 2,
1277     .max_touch_cnt = 5,
1278     .supports_t5r2 = 0,
1279     .support_semi_mt = 0,
1280     .is_button_pad = 1,
1281     .has_wheel = 0,
1282     .wheel_is_hi_res = 0,
1283     .is_haptic_pad = 0,
1284   };
1285   hwprops.max_finger_cnt = 3;
1286   TestInterpreterWrapper wrapper(&ii, &hwprops);
1287 
1288   FingerState finger_states[] = {
1289     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1290     {0, 0, 0, 0, 1, 0, 0, 0, 1, 0},
1291     {0, 0, 0, 0, 1, 0, 0, 0, 2, 0},
1292     {0, 0, 0, 0, 1, 0, 0, 0, 3, 0},
1293     {0, 0, 0, 0, 0, 0, 0, 0, 4, 0},
1294     {0, 0, 0, 0, 0, 0, 0, 0, 5, 0}
1295   };
1296   HardwareState hardware_state = {
1297     // time, buttons, finger count, touch count, finger states pointer
1298     200000, 0, 5, 5, &finger_states[0], 0, 0, 0, 0, 0, 0.0
1299   };
1300   // This used to cause a crash:
1301   Gesture* gs = wrapper.SyncInterpret(hardware_state, nullptr);
1302   EXPECT_EQ(nullptr, gs);
1303 }
1304 
TEST(ImmediateInterpreterTest,AmbiguousPalmCoScrollTest)1305 TEST(ImmediateInterpreterTest, AmbiguousPalmCoScrollTest) {
1306   ImmediateInterpreter ii(nullptr, nullptr);
1307   HardwareProperties hwprops = {
1308     .right = 100,
1309     .bottom = 100,
1310     .res_x = 1,
1311     .res_y = 1,
1312     .orientation_minimum = -1,
1313     .orientation_maximum = 2,
1314     .max_finger_cnt = 5,
1315     .max_touch_cnt = 5,
1316     .supports_t5r2 = 0,
1317     .support_semi_mt = 0,
1318     .is_button_pad = 1,
1319     .has_wheel = 0,
1320     .wheel_is_hi_res = 0,
1321     .is_haptic_pad = 0,
1322   };
1323   TestInterpreterWrapper wrapper(&ii, &hwprops);
1324 
1325   const int kPr = 20;
1326 
1327   const unsigned kPalmFlags = GESTURES_FINGER_POSSIBLE_PALM;
1328 
1329   FingerState finger_states[] = {
1330     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1331     // stationary palm - movement
1332     {0, 0, 0, 0, kPr, 0,  0, 40, 1, kPalmFlags},
1333     {0, 0, 0, 0, kPr, 0, 30, 35, 2, 0},
1334 
1335     {0, 0, 0, 0, kPr, 0,  0, 40, 1, kPalmFlags},
1336     {0, 0, 0, 0, kPr, 0, 30, 40, 2, 0},
1337 
1338     {0, 0, 0, 0, kPr, 0,  0, 40, 1, kPalmFlags},
1339     {0, 0, 0, 0, kPr, 0, 30, 45, 2, 0},
1340 
1341     // Same, but moving palm - scroll
1342     {0, 0, 0, 0, kPr, 0,  0, 35, 3, kPalmFlags},
1343     {0, 0, 0, 0, kPr, 0, 30, 35, 4, 0},
1344 
1345     {0, 0, 0, 0, kPr, 0,  0, 40, 3, kPalmFlags},
1346     {0, 0, 0, 0, kPr, 0, 30, 40, 4, 0},
1347 
1348     {0, 0, 0, 0, kPr, 0,  0, 45, 3, kPalmFlags},
1349     {0, 0, 0, 0, kPr, 0, 30, 45, 4, 0},
1350   };
1351   HardwareState hardware_state[] = {
1352     // time, buttons, finger count, touch count, finger states pointer
1353     make_hwstate(0.0, 0, 2, 2, &finger_states[0]),
1354     make_hwstate(0.1, 0, 2, 2, &finger_states[2]),
1355     make_hwstate(0.2, 0, 2, 2, &finger_states[4]),
1356     make_hwstate(3.0, 0, 2, 2, &finger_states[6]),
1357     make_hwstate(3.1, 0, 2, 2, &finger_states[8]),
1358     make_hwstate(3.2, 0, 2, 2, &finger_states[10]),
1359   };
1360   GestureType expected_gs[] = {
1361     kGestureTypeNull,
1362     kGestureTypeNull,
1363     kGestureTypeMove,
1364     kGestureTypeNull,
1365     kGestureTypeScroll,
1366     kGestureTypeScroll
1367   };
1368   if (ii.pinch_enable_.val_)
1369     // Movement delay is longer when pinch is enabled
1370     expected_gs[2] = kGestureTypeNull;
1371 
1372   ASSERT_EQ(arraysize(expected_gs), arraysize(hardware_state));
1373 
1374   for (size_t i = 0; i < arraysize(hardware_state); ++i) {
1375     Gesture* gs = wrapper.SyncInterpret(hardware_state[i], nullptr);
1376     if (expected_gs[i] == kGestureTypeNull) {
1377       EXPECT_EQ(nullptr, gs) << "gs:" << gs->String();
1378     } else {
1379       ASSERT_NE(nullptr, gs);
1380       EXPECT_EQ(expected_gs[i], gs->type) << "i=" << i
1381                                           << " gs: " << gs->String();
1382     }
1383   }
1384 }
1385 
TEST(ImmediateInterpreterTest,PressureChangeMoveTest)1386 TEST(ImmediateInterpreterTest, PressureChangeMoveTest) {
1387   ImmediateInterpreter ii(nullptr, nullptr);
1388   HardwareProperties hwprops = {
1389     .right = 1000,
1390     .bottom = 1000,
1391     .res_x = 500,
1392     .res_y = 500,
1393     .orientation_minimum = -1,
1394     .orientation_maximum = 2,
1395     .max_finger_cnt = 2,
1396     .max_touch_cnt = 5,
1397     .supports_t5r2 = 0,
1398     .support_semi_mt = 0,
1399     .is_button_pad = 1,
1400     .has_wheel = 0,
1401     .wheel_is_hi_res = 0,
1402     .is_haptic_pad = 0,
1403   };
1404   TestInterpreterWrapper wrapper(&ii, &hwprops);
1405 
1406   const int kBig = 81;  // large pressure
1407   const int kSml = 50;  // small pressure
1408 
1409   FingerState finger_states[] = {
1410     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1411     {0, 0, 0, 0, kSml, 0, 600, 300, 1, 0},
1412     {0, 0, 0, 0, kSml, 0, 600, 400, 1, 0},
1413     {0, 0, 0, 0, kBig, 0, 600, 500, 1, 0},
1414     {0, 0, 0, 0, kBig, 0, 600, 600, 1, 0},
1415   };
1416   HardwareState hardware_state[] = {
1417     // time, buttons, finger count, touch count, finger states pointer
1418     make_hwstate(2000.00, 0, 1, 1, &finger_states[0]),
1419     make_hwstate(2000.01, 0, 1, 1, &finger_states[1]),
1420     make_hwstate(2000.02, 0, 1, 1, &finger_states[2]),
1421     make_hwstate(2000.03, 0, 1, 1, &finger_states[3]),
1422   };
1423 
1424   for (size_t i = 0; i < arraysize(hardware_state); ++i) {
1425     Gesture* result = wrapper.SyncInterpret(hardware_state[i], nullptr);
1426     switch (i) {
1427       case 0:
1428         EXPECT_FALSE(result);
1429         break;
1430       case 2:
1431         ASSERT_TRUE(result);
1432         EXPECT_EQ(kGestureTypeMove, result->type);
1433         EXPECT_EQ(0.0, result->details.move.dy);
1434         break;
1435       case 1:  // fallthrough
1436       case 3:
1437         ASSERT_TRUE(result);
1438         EXPECT_EQ(kGestureTypeMove, result->type);
1439         EXPECT_NE(0.0, result->details.move.dy);
1440         break;
1441     }
1442   }
1443 }
1444 
TEST(ImmediateInterpreterTest,GetGesturingFingersTest)1445 TEST(ImmediateInterpreterTest, GetGesturingFingersTest) {
1446   ImmediateInterpreter ii(nullptr, nullptr);
1447   HardwareProperties hwprops = {
1448     .right = 1000,
1449     .bottom = 1000,
1450     .res_x = 500,
1451     .res_y = 500,
1452     .orientation_minimum = -1,
1453     .orientation_maximum = 2,
1454     .max_finger_cnt = 2,
1455     .max_touch_cnt = 5,
1456     .supports_t5r2 = 0,
1457     .support_semi_mt = 0,
1458     .is_button_pad = 1,
1459     .has_wheel = 0,
1460     .wheel_is_hi_res = 0,
1461     .is_haptic_pad = 0,
1462   };
1463   TestInterpreterWrapper wrapper(&ii, &hwprops);
1464 
1465   FingerState finger_states[] = {
1466     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID, flags
1467     {0, 0, 0, 0, 1, 0, 61, 70, 91, 0},
1468     {0, 0, 0, 0, 1, 0, 62, 65, 92, 0},
1469     {0, 0, 0, 0, 1, 0, 62, 69, 93, 0},
1470     {0, 0, 0, 0, 1, 0, 62, 61, 94, 0}
1471   };
1472   HardwareState hardware_state[] = {
1473     // time, buttons, finger count, finger states pointer
1474     make_hwstate(200000, 0, 0, 0, nullptr),
1475     make_hwstate(200001, 0, 1, 1, &finger_states[0]),
1476     make_hwstate(200002, 0, 2, 2, &finger_states[0]),
1477     make_hwstate(200002, 0, 3, 3, &finger_states[0]),
1478     make_hwstate(200002, 0, 4, 4, &finger_states[0]),
1479   };
1480   // few pointing fingers
1481   ii.ResetSameFingersState(hardware_state[0]);
1482   ii.UpdatePointingFingers(hardware_state[0]);
1483   EXPECT_TRUE(ii.GetGesturingFingers(hardware_state[0]).empty());
1484 
1485   ii.ResetSameFingersState(hardware_state[0]);
1486   ii.UpdatePointingFingers(hardware_state[1]);
1487   std::set<short> ids =
1488       ii.GetGesturingFingers(hardware_state[1]);
1489   EXPECT_EQ(1, ids.size());
1490   EXPECT_TRUE(ids.end() != ids.find(91));
1491 
1492   ii.ResetSameFingersState(hardware_state[0]);
1493   ii.UpdatePointingFingers(hardware_state[2]);
1494   ids = ii.GetGesturingFingers(hardware_state[2]);
1495   EXPECT_EQ(2, ids.size());
1496   EXPECT_TRUE(ids.end() != ids.find(91));
1497   EXPECT_TRUE(ids.end() != ids.find(92));
1498 
1499   ii.ResetSameFingersState(hardware_state[0]);
1500   ii.UpdatePointingFingers(hardware_state[3]);
1501   ids = ii.GetGesturingFingers(hardware_state[3]);
1502   EXPECT_EQ(3, ids.size());
1503   EXPECT_TRUE(ids.end() != ids.find(91));
1504   EXPECT_TRUE(ids.end() != ids.find(92));
1505   EXPECT_TRUE(ids.end() != ids.find(93));
1506 
1507   ii.ResetSameFingersState(hardware_state[0]);
1508   ii.UpdatePointingFingers(hardware_state[4]);
1509   ids = ii.GetGesturingFingers(hardware_state[4]);
1510   EXPECT_EQ(4, ids.size());
1511   EXPECT_TRUE(ids.end() != ids.find(91));
1512   EXPECT_TRUE(ids.end() != ids.find(92));
1513   EXPECT_TRUE(ids.end() != ids.find(93));
1514   EXPECT_TRUE(ids.end() != ids.find(94));
1515 
1516   // T5R2 test
1517   hwprops.supports_t5r2 = 1;
1518   wrapper.Reset(&ii, &hwprops);
1519   ii.ResetSameFingersState(hardware_state[0]);
1520   ii.UpdatePointingFingers(hardware_state[2]);
1521   ids = ii.GetGesturingFingers(hardware_state[2]);
1522   EXPECT_EQ(2, ids.size());
1523   EXPECT_TRUE(ids.end() != ids.find(91));
1524   EXPECT_TRUE(ids.end() != ids.find(92));
1525 }
1526 
TEST(ImmediateInterpreterTest,GetGesturingFingersWithEmptyStateTest)1527 TEST(ImmediateInterpreterTest, GetGesturingFingersWithEmptyStateTest) {
1528   ImmediateInterpreter ii(nullptr, nullptr);
1529   HardwareProperties hwprops = {};
1530   TestInterpreterWrapper wrapper(&ii, &hwprops);
1531 
1532   FingerState finger_states[] = {
1533     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID, flags
1534     {0, 0, 0, 0, 1, 0, 61, 70, 91, 0},
1535     {0, 0, 0, 0, 1, 0, 62, 65, 92, 0},
1536     {0, 0, 0, 0, 1, 0, 62, 69, 93, 0},
1537     {0, 0, 0, 0, 1, 0, 62, 61, 94, 0},
1538     {0, 0, 0, 0, 1, 0, 63, 80, 95, 0},
1539   };
1540   HardwareState five_finger_hwstate =
1541       make_hwstate(200000, 0, 5, 5, &finger_states[0]);
1542   HardwareState no_finger_hwstate = make_hwstate(200001, 0, 0, 0, nullptr);
1543   ii.ResetSameFingersState(five_finger_hwstate);
1544   ii.UpdatePointingFingers(five_finger_hwstate);
1545   EXPECT_TRUE(ii.GetGesturingFingers(no_finger_hwstate).empty());
1546 }
1547 
1548 namespace {
MkSet()1549 std::set<short> MkSet() {
1550   return std::set<short>();
1551 }
MkSet(short the_id)1552 std::set<short> MkSet(short the_id) {
1553   std::set<short> ret;
1554   ret.insert(the_id);
1555   return ret;
1556 }
MkSet(short id1,short id2)1557 std::set<short> MkSet(short id1, short id2) {
1558   std::set<short> ret;
1559   ret.insert(id1);
1560   ret.insert(id2);
1561   return ret;
1562 }
MkSet(short id1,short id2,short id3)1563 std::set<short> MkSet(short id1, short id2, short id3) {
1564   std::set<short> ret;
1565   ret.insert(id1);
1566   ret.insert(id2);
1567   ret.insert(id3);
1568   return ret;
1569 }
1570 }  // namespace{}
1571 
TEST(ImmediateInterpreterTest,TapRecordTest)1572 TEST(ImmediateInterpreterTest, TapRecordTest) {
1573   ImmediateInterpreter ii(nullptr, nullptr);
1574   HardwareProperties hwprops = {};
1575   TestInterpreterWrapper wrapper(&ii, &hwprops);
1576   TapRecord tr(&ii);
1577   EXPECT_FALSE(tr.TapComplete());
1578   // two finger IDs:
1579   const short kF1 = 91;
1580   const short kF2 = 92;
1581   const float kTapMoveDist = 1.0;  // mm
1582   ii.tap_min_pressure_.val_ = 25;
1583 
1584   FingerState fs[] = {
1585     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
1586     {0, 0, 0, 0, 50, 0, 4, 4, kF1, 0},
1587     {0, 0, 0, 0, 75, 0, 4, 9, kF2, 0},
1588     {0, 0, 0, 0, 50, 0, 7, 4, kF1, 0}
1589   };
1590   HardwareState nullstate = make_hwstate(0.0, 0, 0, 0, nullptr);
1591   HardwareState hw[] = {
1592     // time, buttons, finger count, touch count, finger states pointer
1593     make_hwstate(0.0, 0, 1, 1, &fs[0]),
1594     make_hwstate(0.1, 0, 2, 2, &fs[0]),
1595     make_hwstate(0.2, 0, 1, 1, &fs[1]),
1596     make_hwstate(0.3, 0, 2, 2, &fs[0]),
1597     make_hwstate(0.4, 0, 1, 1, &fs[1]),
1598     make_hwstate(0.5, 0, 1, 1, &fs[2]),
1599   };
1600 
1601   // Hack: TapRecord uses ImmediateInterpreter's FingerMetrics for origin
1602   // timestamps, so we need to populate those.
1603   ii.metrics_->Update(hw[0]);
1604   tr.Update(hw[0], nullstate, MkSet(kF1), MkSet(), MkSet());
1605   EXPECT_FALSE(tr.Moving(hw[0], kTapMoveDist));
1606   EXPECT_FALSE(tr.TapComplete());
1607   ii.metrics_->Update(hw[1]);
1608   tr.Update(hw[1], hw[0], MkSet(), MkSet(), MkSet());
1609   EXPECT_FALSE(tr.Moving(hw[1], kTapMoveDist));
1610   EXPECT_FALSE(tr.TapComplete());
1611   tr.Update(hw[2], hw[1], MkSet(), MkSet(kF1), MkSet());
1612   EXPECT_FALSE(tr.Moving(hw[2], kTapMoveDist));
1613   EXPECT_TRUE(tr.TapComplete());
1614   EXPECT_EQ(GESTURES_BUTTON_LEFT, tr.TapType());
1615 
1616   tr.Clear();
1617   EXPECT_FALSE(tr.TapComplete());
1618   tr.Update(hw[2], hw[1], MkSet(kF2), MkSet(), MkSet());
1619   EXPECT_FALSE(tr.Moving(hw[2], kTapMoveDist));
1620   EXPECT_FALSE(tr.TapComplete());
1621   tr.Update(hw[3], hw[2], MkSet(kF1), MkSet(), MkSet(kF2));
1622   EXPECT_FALSE(tr.Moving(hw[3], kTapMoveDist));
1623   EXPECT_FALSE(tr.TapComplete());
1624   tr.Update(hw[4], hw[3], MkSet(), MkSet(kF1), MkSet());
1625   EXPECT_FALSE(tr.Moving(hw[4], kTapMoveDist));
1626   EXPECT_TRUE(tr.TapComplete());
1627 
1628   tr.Clear();
1629   EXPECT_FALSE(tr.TapComplete());
1630   tr.Update(hw[0], nullstate, MkSet(kF1), MkSet(), MkSet());
1631   tr.Update(hw[5], hw[4], MkSet(), MkSet(), MkSet());
1632   EXPECT_TRUE(tr.Moving(hw[5], kTapMoveDist));
1633   EXPECT_FALSE(tr.TapComplete());
1634 
1635   // This should log an error
1636   tr.Clear();
1637   tr.Update(hw[2], hw[1], MkSet(), MkSet(kF1), MkSet());
1638 }
1639 
1640 namespace {
1641 
1642 // Contains inputs to be made to the tap-to-click state machine, and the
1643 // expected state and output of the machine after those inputs.
1644 struct HWStateGs {
1645   HardwareState hws;
1646   // If >= 0, no HardwareState is passed into the state machine, simulating a
1647   // callback.
1648   stime_t callback_now;
1649   // Tracking IDs of fingers that are considered to be gesturing.
1650   std::set<short> gesturing_fingers;
1651 
1652   unsigned expected_down;
1653   unsigned expected_up;
1654   ImmediateInterpreter::TapToClickState expected_state;
1655   // Whether the state machine is expected to set a timeout after receiving
1656   // these inputs.
1657   bool timeout;
1658 };
1659 
1660 // Shorter names so that HWStateGs definitions take only 1 line each.
1661 typedef ImmediateInterpreter::TapToClickState TapState;
1662 constexpr TapState kIdl = ImmediateInterpreter::kTtcIdle;
1663 constexpr TapState kFTB = ImmediateInterpreter::kTtcFirstTapBegan;
1664 constexpr TapState kTpC = ImmediateInterpreter::kTtcTapComplete;
1665 constexpr TapState kSTB = ImmediateInterpreter::kTtcSubsequentTapBegan;
1666 constexpr TapState kDrg = ImmediateInterpreter::kTtcDrag;
1667 constexpr TapState kDRl = ImmediateInterpreter::kTtcDragRelease;
1668 constexpr TapState kDRt = ImmediateInterpreter::kTtcDragRetouch;
1669 constexpr unsigned kBL = GESTURES_BUTTON_LEFT;
1670 constexpr unsigned kBM = GESTURES_BUTTON_MIDDLE;
1671 constexpr unsigned kBR = GESTURES_BUTTON_RIGHT;
1672 
1673 }  // namespace {}
1674 
1675 class TapToClickStateMachineTest : public ::testing::Test {
1676 protected:
set_gesture_properties()1677   void set_gesture_properties() {
1678     ii_->drag_lock_enable_.val_ = true;
1679     ii_->motion_tap_prevent_timeout_.val_ = 0;
1680     ii_->tapping_finger_min_separation_.val_ = 1.0;
1681     ii_->tap_drag_timeout_.val_ = 0.05;
1682     ii_->tap_enable_.val_ = true;
1683     ii_->tap_drag_enable_.val_ = tap_drag_enable_;
1684     ii_->tap_move_dist_.val_ = 1.0;
1685     ii_->tap_timeout_.val_ = tap_timeout_;
1686     ii_->inter_tap_timeout_.val_ = 0.05;
1687     ii_->three_finger_click_enable_.val_ = true;
1688     ii_->t5r2_three_finger_click_enable_.val_ = true;
1689     ii_->zero_finger_click_enable_.val_ = true;
1690   }
1691 
check_hwstates(const std::vector<HWStateGs> & states,std::optional<std::string> label=std::nullopt)1692   void check_hwstates(const std::vector<HWStateGs>& states,
1693                       std::optional<std::string> label = std::nullopt) {
1694     EXPECT_EQ(kIdl, ii_->tap_to_click_state_);
1695     for (size_t i = 0; i < states.size(); ++i) {
1696       std::string label_or_empty = label.has_value() ? " (" + *label + ")" : "";
1697       SCOPED_TRACE(StringPrintf("State %zu%s", i, label_or_empty.c_str()));
1698 
1699       unsigned buttons_down = 0;
1700       unsigned buttons_up = 0;
1701       stime_t timeout = NO_DEADLINE;
1702       bool same_fingers = false;
1703       const HardwareState* hwstate = &states[i].hws;
1704       stime_t now = states[i].callback_now;
1705       if (states[i].callback_now >= 0.0) {
1706         hwstate = nullptr;
1707       } else {
1708         now = states[i].hws.timestamp;
1709       }
1710 
1711       if (!hwstate || hwstate->timestamp != 0.0) {
1712         same_fingers = ii_->state_buffer_.Get(1).SameFingersAs(states[i].hws);
1713       }
1714 
1715       if (hwstate)
1716         ii_->state_buffer_.PushState(*hwstate);
1717       // TODO(b/307933752): this is unrealistic compared to the actual code that
1718       // tracks origin timestamps, but making it more realistic (by calling
1719       // ii_->metrics_->Update(*hwstate)) causes
1720       // OneFingerTapThenMoveAfterDelayDoesNotDrag to fail.
1721       for (auto finger: states[i].gesturing_fingers) {
1722         ii_->metrics_->SetFingerOriginTimestampForTesting(finger, 0);
1723       }
1724       ii_->UpdateTapState(
1725           hwstate, states[i].gesturing_fingers, same_fingers, now,
1726           &buttons_down, &buttons_up, &timeout);
1727       ii_->prev_gs_fingers_ = states[i].gesturing_fingers;
1728       EXPECT_EQ(states[i].expected_down, buttons_down);
1729       EXPECT_EQ(states[i].expected_up, buttons_up);
1730       if (states[i].timeout)
1731         EXPECT_GT(timeout, 0.0);
1732       else
1733         EXPECT_DOUBLE_EQ(NO_DEADLINE, timeout);
1734       EXPECT_EQ(states[i].expected_state, ii_->tap_to_click_state_);
1735     }
1736   }
1737 
run_test(const std::vector<HWStateGs> & states,std::optional<std::string> label=std::nullopt)1738   void run_test(const std::vector<HWStateGs>& states,
1739                 std::optional<std::string> label = std::nullopt) {
1740     ii_.reset(new ImmediateInterpreter(nullptr, nullptr));
1741     TestInterpreterWrapper wrapper(ii_.get(), &hwprops_);
1742     set_gesture_properties();
1743     check_hwstates(states, label);
1744   }
1745 
1746   // Algorithmically adds a resting thumb to all cases in states, and then tests
1747   // them.
run_test_with_added_resting_thumb(const std::vector<HWStateGs> & states)1748   void run_test_with_added_resting_thumb(const std::vector<HWStateGs>& states) {
1749     std::vector<HWStateGs> states_with_thumbs = states;
1750     std::vector<std::vector<FingerState> > thumb_fs(states.size());
1751     const FingerState fs_thumb = {0, 0, 0, 0, 80, 0, 5, 9, 71, 0};
1752     // Start out with the thumb being able to gesture.
1753     bool thumb_gestures = true;
1754     for (size_t i = 0; i < states_with_thumbs.size(); ++i) {
1755       HardwareState* hs = &states_with_thumbs[i].hws;
1756       if (hs->finger_cnt > 0) {
1757         // Once a finger is present, the thumb can't gesture.
1758         thumb_gestures = false;
1759       }
1760       std::vector<FingerState>& newfs = thumb_fs[i];
1761       newfs.resize(hs->finger_cnt + 1);
1762       newfs[0] = fs_thumb;
1763       for (size_t j = 0; j < hs->finger_cnt; ++j)
1764         newfs[j + 1] = hs->fingers[j];
1765       std::set<short>& gs = states_with_thumbs[i].gesturing_fingers;
1766       if (thumb_gestures)
1767         gs.insert(fs_thumb.tracking_id);
1768       hs->fingers = &thumb_fs[i][0];
1769       hs->finger_cnt++;
1770       hs->touch_cnt++;
1771     }
1772 
1773     run_test(states_with_thumbs, "with resting thumb");
1774   }
1775 
1776   // Removes pressure data from the states, then tests them.
run_test_without_pressure_data(const std::vector<HWStateGs> & states)1777   void run_test_without_pressure_data(const std::vector<HWStateGs>& states) {
1778     HardwareProperties hwprops = hwprops_;
1779     hwprops.reports_pressure = false;
1780 
1781     std::vector<HWStateGs> states_without_pressure = states;
1782     std::vector<std::vector<FingerState>> finger_states(states.size());
1783     for (size_t i = 0; i < states_without_pressure.size(); i++) {
1784       HWStateGs& state = states_without_pressure[i];
1785       if (state.hws.finger_cnt == 0) {
1786         continue;
1787       }
1788       for (size_t j = 0; j < state.hws.finger_cnt; j++) {
1789         FingerState fs_without_pressure = state.hws.fingers[j];
1790         fs_without_pressure.pressure = 0;
1791         finger_states[i].push_back(fs_without_pressure);
1792       }
1793       state.hws.fingers = &finger_states[i][0];
1794     }
1795 
1796     ii_.reset(new ImmediateInterpreter(nullptr, nullptr));
1797     TestInterpreterWrapper wrapper(ii_.get(), &hwprops);
1798     set_gesture_properties();
1799     check_hwstates(states_without_pressure, "without pressure data");
1800   }
1801 
1802   std::unique_ptr<ImmediateInterpreter> ii_;
1803   bool tap_drag_enable_ = true;
1804   double tap_timeout_ = 0.05;
1805  private:
1806   const HardwareProperties hwprops_ = {
1807     .right = 200,
1808     .bottom = 200,
1809     .res_x = 1.0,  // pixels/TP width
1810     .res_y = 1.0,  // pixels/TP height
1811     .orientation_minimum = -1,
1812     .orientation_maximum = 2,
1813     .max_finger_cnt = 5,
1814     .max_touch_cnt = 5,
1815     .supports_t5r2 = false,
1816     .support_semi_mt = false,
1817     .is_button_pad = true,
1818     .has_wheel = false,
1819     .wheel_is_hi_res = false,
1820     .is_haptic_pad = false,
1821   };
1822 };
1823 
TEST_F(TapToClickStateMachineTest,OneFingerTap)1824 TEST_F(TapToClickStateMachineTest, OneFingerTap) {
1825   FingerState fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
1826   std::vector<HWStateGs> states = {
1827     {make_hwstate(0.00, 0, 1, 1, &fs), -1, MkSet(91), 0, 0, kFTB, false},
1828     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kTpC, true},
1829     {make_hwstate(0.07, 0, 0, 0, nullptr), .07, MkSet(), kBL, kBL, kIdl, false},
1830   };
1831   run_test(states);
1832   run_test_with_added_resting_thumb(states);
1833   run_test_without_pressure_data(states);
1834 }
1835 
TEST_F(TapToClickStateMachineTest,OneFingerTapWithoutDraggingEnabled)1836 TEST_F(TapToClickStateMachineTest, OneFingerTapWithoutDraggingEnabled) {
1837   FingerState fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
1838   std::vector<HWStateGs> states = {
1839     {make_hwstate(0.00, 0, 1, 1, &fs), -1, MkSet(91), 0, 0, kFTB, false},
1840     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), kBL, kBL, kIdl, false},
1841   };
1842   tap_drag_enable_ = false;
1843   run_test(states);
1844   run_test_with_added_resting_thumb(states);
1845   run_test_without_pressure_data(states);
1846 }
1847 
TEST_F(TapToClickStateMachineTest,OneFingerTapWithClick)1848 TEST_F(TapToClickStateMachineTest, OneFingerTapWithClick) {
1849   FingerState fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
1850   std::vector<HWStateGs> states = {
1851     {make_hwstate(0.00, kBL, 1, 1, &fs), -1, MkSet(91), 0, 0, kIdl, false},
1852     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
1853     {make_hwstate(0.07, 0, 0, 0, nullptr), .07, MkSet(), 0, 0, kIdl, false},
1854   };
1855   run_test(states);
1856   run_test_with_added_resting_thumb(states);
1857   run_test_without_pressure_data(states);
1858 }
1859 
TEST_F(TapToClickStateMachineTest,OneFingerSwipe)1860 TEST_F(TapToClickStateMachineTest, OneFingerSwipe) {
1861   FingerState fs[] = {
1862     {0, 0, 0, 0, 50, 0, 4, 4, 95, 0},
1863     {0, 0, 0, 0, 50, 0, 6, 4, 95, 0},
1864     {0, 0, 0, 0, 50, 0, 8, 4, 95, 0},
1865   };
1866   std::vector<HWStateGs> states = {
1867     {make_hwstate(0.00, 0, 1, 1, &fs[0]), -1, MkSet(95), 0, 0, kFTB, false},
1868     {make_hwstate(0.01, 0, 1, 1, &fs[1]), -1, MkSet(95), 0, 0, kIdl, false},
1869     {make_hwstate(0.02, 0, 1, 1, &fs[2]), -1, MkSet(95), 0, 0, kIdl, false},
1870     {make_hwstate(0.03, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
1871   };
1872   run_test(states);
1873   run_test_with_added_resting_thumb(states);
1874   run_test_without_pressure_data(states);
1875 }
1876 
TEST_F(TapToClickStateMachineTest,DoubleOneFingerTap)1877 TEST_F(TapToClickStateMachineTest, DoubleOneFingerTap) {
1878   FingerState fs[] = {
1879     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
1880     {0, 0, 0, 0, 50, 0, 4, 4, 93, 0},
1881   };
1882   std::vector<HWStateGs> states = {
1883     {make_hwstate(0.00, 0, 1, 1, &fs[0]), -1, MkSet(91), 0, 0, kFTB, false},
1884     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kTpC, true},
1885     {make_hwstate(0.02, 0, 1, 1, &fs[1]), -1, MkSet(93), 0, 0, kSTB, false},
1886     {make_hwstate(0.03, 0, 0, 0, nullptr), -1, MkSet(), kBL, kBL, kTpC, true},
1887     {make_hwstate(0.09, 0, 0, 0, nullptr), .09, MkSet(), kBL, kBL, kIdl, false},
1888   };
1889   run_test(states);
1890   run_test_with_added_resting_thumb(states);
1891   run_test_without_pressure_data(states);
1892 }
1893 
TEST_F(TapToClickStateMachineTest,TripleOneFingerTap)1894 TEST_F(TapToClickStateMachineTest, TripleOneFingerTap) {
1895   FingerState fs[] = {
1896     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
1897     {0, 0, 0, 0, 50, 0, 4, 4, 93, 0},
1898     {0, 0, 0, 0, 50, 0, 4, 4, 94, 0},
1899   };
1900   std::vector<HWStateGs> states = {
1901     {make_hwstate(0.00, 0, 1, 1, &fs[0]), -1, MkSet(91), 0, 0, kFTB, false},
1902     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kTpC, true},
1903     {make_hwstate(0.02, 0, 1, 1, &fs[1]), -1, MkSet(93), 0, 0, kSTB, false},
1904     {make_hwstate(0.03, 0, 0, 0, nullptr), -1, MkSet(), kBL, kBL, kTpC, true},
1905     {make_hwstate(0.04, 0, 1, 1, &fs[2]), -1, MkSet(94), 0, 0, kSTB, false},
1906     {make_hwstate(0.05, 0, 0, 0, nullptr), -1, MkSet(), kBL, kBL, kTpC, true},
1907     {make_hwstate(0.11, 0, 0, 0, nullptr), .11, MkSet(), kBL, kBL, kIdl, false},
1908   };
1909   run_test(states);
1910   run_test_with_added_resting_thumb(states);
1911   run_test_without_pressure_data(states);
1912 }
1913 
TEST_F(TapToClickStateMachineTest,OneFingerTapAndDrag)1914 TEST_F(TapToClickStateMachineTest, OneFingerTapAndDrag) {
1915   FingerState tap_fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
1916   FingerState drag_fs[] = {
1917     {0, 0, 0, 0, 50, 0, 4, 4, 95, 0},
1918     {0, 0, 0, 0, 50, 0, 6, 4, 95, 0},
1919     {0, 0, 0, 0, 50, 0, 8, 4, 95, 0},
1920   };
1921   std::vector<HWStateGs> states = {
1922     {make_hwstate(0.00,0,1,1,&tap_fs),-1,MkSet(91),0,0,kFTB,false},
1923     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),0,0,kTpC,true},
1924     {make_hwstate(0.02,0,1,1,&drag_fs[0]),-1,MkSet(95),0,0,kSTB,false},
1925     {make_hwstate(0.13,0,1,1,&drag_fs[1]),-1,MkSet(95),kBL,0,kDrg,false},
1926     {make_hwstate(0.14,0,1,1,&drag_fs[2]),-1,MkSet(95),0,0,kDrg,false},
1927     {make_hwstate(0.15,0,0,0,nullptr),-1,MkSet(),0,0,kDRl,true},
1928     {make_hwstate(0.99,0,0,0,nullptr),.99,MkSet(),0,kBL,kIdl,false},
1929   };
1930   run_test(states);
1931   run_test_with_added_resting_thumb(states);
1932   run_test_without_pressure_data(states);
1933 }
1934 
TEST_F(TapToClickStateMachineTest,OneFingerTapThenMoveAfterDelayDoesNotDrag)1935 TEST_F(TapToClickStateMachineTest, OneFingerTapThenMoveAfterDelayDoesNotDrag) {
1936   // TODO(b/307933752): this test fails if more realistic origin timestamps are
1937   // set in TapToClickStateMachineTest::check_hwstates (i.e. calling
1938   // ii_->metrics_->Update instead of setting the origin timestamps of
1939   // gesturing_fingers to 0). Check whether that's a problem with the test or
1940   // the code it's testing.
1941   FingerState tap_fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
1942   FingerState move_fs[] = {
1943     {0, 0, 0, 0, 50, 0, 4, 4, 95, 0},
1944     {0, 0, 0, 0, 50, 0, 6, 4, 95, 0},
1945     {0, 0, 0, 0, 50, 0, 8, 4, 95, 0},
1946   };
1947   std::vector<HWStateGs> states = {
1948     {make_hwstate(0.00,0,1,1,&tap_fs),-1,MkSet(91),0,0,kFTB,false},
1949     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),0,0,kTpC,true},
1950     {make_hwstate(0.22,0,1,1,&move_fs[0]),-1,MkSet(95),kBL,kBL,kIdl,false},
1951     {make_hwstate(0.23,0,1,1,&move_fs[1]),-1,MkSet(95),0,0,kIdl,false},
1952     {make_hwstate(0.25,0,1,1,&move_fs[2]),-1,MkSet(95),0,0,kIdl,false},
1953     {make_hwstate(0.26,0,0,0,nullptr),-1,MkSet(),0,0,kIdl,false},
1954     {make_hwstate(0.99,0,0,0,nullptr),.99,MkSet(),0,0,kIdl,false},
1955   };
1956   run_test(states);
1957   run_test_with_added_resting_thumb(states);
1958   run_test_without_pressure_data(states);
1959 }
1960 
1961 
TEST_F(TapToClickStateMachineTest,OneFingerTapAndMoveDrags)1962 TEST_F(TapToClickStateMachineTest, OneFingerTapAndMoveDrags) {
1963   FingerState tap_fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
1964   FingerState move_fs[] = {
1965     {0, 0, 0, 0, 50, 0, 4, 4, 95, 0},
1966     {0, 0, 0, 0, 50, 0, 6, 4, 95, 0},
1967     {0, 0, 0, 0, 50, 0, 8, 4, 95, 0},
1968   };
1969   std::vector<HWStateGs> states = {
1970     {make_hwstate(0.00,0,1,1,&tap_fs),-1,MkSet(91),0,0,kFTB,false},
1971     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),0,0,kTpC,true},
1972     {make_hwstate(0.02,0,1,1,&move_fs[0]),-1,MkSet(95),0,0,kSTB,false},
1973     {make_hwstate(0.03,0,1,1,&move_fs[1]),-1,MkSet(95),kBL,0,kDrg,false},
1974     {make_hwstate(0.04,0,1,1,&move_fs[2]),-1,MkSet(95),0,0,kDrg,false},
1975     {make_hwstate(0.05,0,0,0,nullptr),-1,MkSet(),0,0,kDRl,true},
1976     {make_hwstate(0.99,0,0,0,nullptr),.99,MkSet(),0,kBL,kIdl,false},
1977   };
1978   run_test(states);
1979   run_test_with_added_resting_thumb(states);
1980   run_test_without_pressure_data(states);
1981 }
1982 
TEST_F(TapToClickStateMachineTest,OneFingerTapDragLock)1983 TEST_F(TapToClickStateMachineTest, OneFingerTapDragLock) {
1984   FingerState tap_fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
1985   FingerState drag_fs[] = {
1986     {0, 0, 0, 0, 50, 0, 4, 4, 95, 0},
1987     {0, 0, 0, 0, 50, 0, 6, 4, 95, 0},
1988     {0, 0, 0, 0, 50, 0, 8, 4, 95, 0},
1989     {0, 0, 0, 0, 50, 0, 4, 4, 96, 0},
1990     {0, 0, 0, 0, 50, 0, 6, 4, 96, 0},
1991     {0, 0, 0, 0, 50, 0, 8, 4, 96, 0},
1992   };
1993   std::vector<HWStateGs> states = {
1994     {make_hwstate(0.00,0,1,1,&tap_fs),-1,MkSet(91),0,0,kFTB,false},
1995     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),0,0,kTpC,true},
1996     {make_hwstate(0.02,0,1,1,&drag_fs[0]),-1,MkSet(95),0,0,kSTB,false},
1997     {make_hwstate(0.08,0,1,1,&drag_fs[1]),-1,MkSet(95),kBL,0,kDrg,false},
1998     {make_hwstate(0.09,0,1,1,&drag_fs[2]),-1,MkSet(95),0,0,kDrg,false},
1999     {make_hwstate(0.10,0,0,0,nullptr),-1,MkSet(),0,0,kDRl,true},
2000     {make_hwstate(0.11,0,1,1,&drag_fs[3]),-1,MkSet(96),0,0,kDRt,false},
2001     {make_hwstate(0.12,0,1,1,&drag_fs[4]),-1,MkSet(96),0,0,kDrg,false},
2002     {make_hwstate(0.13,0,1,1,&drag_fs[5]),-1,MkSet(96),0,0,kDrg,false},
2003     {make_hwstate(0.14,0,0,0,nullptr),-1,MkSet(),0,0,kDRl,true},
2004     {make_hwstate(0.99,0,0,0,nullptr),.99,MkSet(),0,kBL,kIdl,false},
2005   };
2006   run_test(states);
2007   run_test_with_added_resting_thumb(states);
2008   run_test_without_pressure_data(states);
2009 }
2010 
TEST_F(TapToClickStateMachineTest,OneFingerLongPress)2011 TEST_F(TapToClickStateMachineTest, OneFingerLongPress) {
2012   FingerState fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
2013   std::vector<HWStateGs> states = {
2014     {make_hwstate(0.00, 0, 1, 1, &fs), -1, MkSet(91), 0, 0, kFTB, false},
2015     {make_hwstate(0.02, 0, 1, 1, &fs), -1, MkSet(91), 0, 0, kFTB, false},
2016     {make_hwstate(0.04, 0, 1, 1, &fs), -1, MkSet(91), 0, 0, kFTB, false},
2017     {make_hwstate(0.06, 0, 1, 1, &fs), -1, MkSet(91), 0, 0, kIdl, false},
2018     {make_hwstate(0.07, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
2019   };
2020   run_test(states);
2021   run_test_with_added_resting_thumb(states);
2022   run_test_without_pressure_data(states);
2023 }
2024 
TEST_F(TapToClickStateMachineTest,OneFingerTapThenLongPress)2025 TEST_F(TapToClickStateMachineTest, OneFingerTapThenLongPress) {
2026   FingerState tap_fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
2027   FingerState press_fs = {0, 0, 0, 0, 50, 0, 4, 4, 95, 0};
2028   std::vector<HWStateGs> states = {
2029     {make_hwstate(0.00,0,1,1,&tap_fs),-1,MkSet(91),0,0,kFTB,false},
2030     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),0,0,kTpC,true},
2031     {make_hwstate(0.02,0,1,1,&press_fs),-1,MkSet(95),0,0,kSTB,false},
2032     {make_hwstate(0.14,0,1,1,&press_fs),-1,MkSet(95),kBL,0,kDrg,false},
2033     {make_hwstate(0.16,0,1,1,&press_fs),-1,MkSet(95),0,0,kDrg,false},
2034     {make_hwstate(0.18,0,1,1,&press_fs),-1,MkSet(95),0,0,kDrg,false},
2035     {make_hwstate(0.19,0,0,0,nullptr),-1,MkSet(),0,0,kDRl,true},
2036     {make_hwstate(0.99,0,0,0,nullptr),.99,MkSet(),0,kBL,kIdl,false},
2037   };
2038   run_test(states);
2039   run_test_with_added_resting_thumb(states);
2040   run_test_without_pressure_data(states);
2041 }
2042 
TEST_F(TapToClickStateMachineTest,TwoFingerTap)2043 TEST_F(TapToClickStateMachineTest, TwoFingerTap) {
2044   FingerState fs[] = {
2045     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2046     {0, 0, 0, 0, 50, 0, 9, 1, 98, 0},
2047   };
2048   std::vector<HWStateGs> states = {
2049     {make_hwstate(0.00, 0, 2, 2, &fs[0]), -1, MkSet(97, 98), 0, 0, kFTB, false},
2050     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), kBR, kBR, kIdl, false},
2051     {make_hwstate(0.07, 0, 0, 0, nullptr), .07, MkSet(), 0, 0, kIdl, false},
2052   };
2053   run_test(states);
2054   run_test_with_added_resting_thumb(states);
2055   run_test_without_pressure_data(states);
2056 }
2057 
TEST_F(TapToClickStateMachineTest,ThreeFingerTap)2058 TEST_F(TapToClickStateMachineTest, ThreeFingerTap) {
2059   FingerState fs[] = {
2060     {0, 0, 0, 0, 50, 0,  4, 1, 97, 0},
2061     {0, 0, 0, 0, 50, 0,  9, 1, 98, 0},
2062     {0, 0, 0, 0, 50, 0, 14, 1, 99, 0},
2063   };
2064   std::vector<HWStateGs> states = {
2065     {make_hwstate(0.00,0,3,3,&fs[0]),-1,MkSet(97,98,99),0,0,kFTB,false},
2066     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),kBM,kBM,kIdl,false},
2067     {make_hwstate(0.07,0,0,0,nullptr),.07,MkSet(),0,0,kIdl,false},
2068   };
2069   run_test(states);
2070   run_test_with_added_resting_thumb(states);
2071   run_test_without_pressure_data(states);
2072 }
2073 
TEST_F(TapToClickStateMachineTest,TwoFingerTapWithOneFingerVeryLightGivesLeftClick)2074 TEST_F(TapToClickStateMachineTest,
2075        TwoFingerTapWithOneFingerVeryLightGivesLeftClick) {
2076   FingerState fs[] = {
2077     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2078     {0, 0, 0, 0,  3, 0, 9, 1, 98, 0},
2079   };
2080   std::vector<HWStateGs> states = {
2081     {make_hwstate(0.00, 0, 2, 2, &fs[0]), -1, MkSet(97, 98), 0, 0, kFTB, false},
2082     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kTpC, true},
2083     {make_hwstate(0.07, 0, 0, 0, nullptr), .07, MkSet(), kBL, kBL, kIdl, false},
2084   };
2085   run_test(states);
2086   run_test_with_added_resting_thumb(states);
2087 }
2088 
TEST_F(TapToClickStateMachineTest,TwoFingerScroll)2089 TEST_F(TapToClickStateMachineTest, TwoFingerScroll) {
2090   FingerState fs[] = {
2091     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2092     {0, 0, 0, 0, 50, 0, 9, 1, 98, 0},
2093     {0, 0, 0, 0, 50, 0, 4, 5, 97, 0},
2094     {0, 0, 0, 0, 50, 0, 9, 5, 98, 0},
2095     {0, 0, 0, 0, 50, 0, 4, 9, 97, 0},
2096     {0, 0, 0, 0, 50, 0, 9, 9, 98, 0},
2097   };
2098   std::vector<HWStateGs> states = {
2099     {make_hwstate(0.00, 0, 2, 2, &fs[0]), -1, MkSet(97, 98), 0, 0, kFTB, false},
2100     {make_hwstate(0.01, 0, 2, 2, &fs[2]), -1, MkSet(97, 98), 0, 0, kIdl, false},
2101     {make_hwstate(0.02, 0, 2, 2, &fs[4]), -1, MkSet(97, 98), 0, 0, kIdl, false},
2102     {make_hwstate(0.03, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
2103   };
2104   run_test(states);
2105   run_test_with_added_resting_thumb(states);
2106   run_test_without_pressure_data(states);
2107 }
2108 
TEST_F(TapToClickStateMachineTest,OneFingerTapThenTwoFingerTap)2109 TEST_F(TapToClickStateMachineTest, OneFingerTapThenTwoFingerTap) {
2110   FingerState fs[] = {
2111     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2112 
2113     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2114     {0, 0, 0, 0, 50, 0, 9, 1, 98, 0},
2115   };
2116   std::vector<HWStateGs> states = {
2117     {make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
2118     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),0,0,kTpC,true},
2119     {make_hwstate(0.02,0,2,2,&fs[1]),-1,MkSet(97,98),kBL,kBL,kFTB,false},
2120     {make_hwstate(0.03,0,0,0,nullptr),-1,MkSet(),kBR,kBR,kIdl,false},
2121     {make_hwstate(0.09,0,0,0,nullptr),.09,MkSet(),0,0,kIdl,false},
2122   };
2123   run_test(states);
2124   run_test_with_added_resting_thumb(states);
2125   run_test_without_pressure_data(states);
2126 }
2127 
TEST_F(TapToClickStateMachineTest,OneFingerTapThenMultiFrameTwoFingerTap)2128 TEST_F(TapToClickStateMachineTest, OneFingerTapThenMultiFrameTwoFingerTap) {
2129   FingerState fs[] = {
2130     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2131 
2132     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2133     {0, 0, 0, 0, 50, 0, 9, 1, 98, 0},
2134   };
2135   std::vector<HWStateGs> states = {
2136     {make_hwstate(0.00, 0, 1, 1, &fs[0]), -1, MkSet(91), 0, 0, kFTB, false},
2137     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kTpC, true},
2138     {make_hwstate(0.02, 0, 1, 1, &fs[1]), -1, MkSet(97), 0, 0, kSTB, false},
2139     {make_hwstate(0.03, 0, 1, 1, &fs[2]), -1, MkSet(98), kBL, kBL, kFTB, false},
2140     {make_hwstate(0.04, 0, 0, 0, nullptr), -1, MkSet(), kBR, kBR, kIdl, false},
2141   };
2142   run_test(states);
2143   run_test_with_added_resting_thumb(states);
2144   run_test_without_pressure_data(states);
2145 }
2146 
TEST_F(TapToClickStateMachineTest,TwoFingerTapThenOneFingerTap)2147 TEST_F(TapToClickStateMachineTest, TwoFingerTapThenOneFingerTap) {
2148   FingerState fs[] = {
2149     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2150     {0, 0, 0, 0, 50, 0, 9, 1, 98, 0},
2151     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2152   };
2153   std::vector<HWStateGs> states = {
2154     {make_hwstate(0.00, 0, 2, 2, &fs[0]), -1, MkSet(97, 98), 0, 0, kFTB, false},
2155     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), kBR, kBR, kIdl, false},
2156     {make_hwstate(0.02, 0, 1, 1, &fs[2]), -1, MkSet(91), 0, 0, kFTB, false},
2157     {make_hwstate(0.03, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kTpC, true},
2158     {make_hwstate(0.09, 0, 0, 0, nullptr), .09, MkSet(), kBL, kBL, kIdl, false},
2159   };
2160   run_test(states);
2161   run_test_with_added_resting_thumb(states);
2162   run_test_without_pressure_data(states);
2163 }
2164 
TEST_F(TapToClickStateMachineTest,ThreeFingerTapThenOneFingerTap)2165 TEST_F(TapToClickStateMachineTest, ThreeFingerTapThenOneFingerTap) {
2166   FingerState fs[] = {
2167     {0, 0, 0, 0, 50, 0,  4, 1, 97, 0},
2168     {0, 0, 0, 0, 50, 0,  9, 1, 98, 0},
2169     {0, 0, 0, 0, 50, 0, 14, 1, 99, 0},
2170     {0, 0, 0, 0, 50, 0,  4, 4, 91, 0},
2171   };
2172   std::vector<HWStateGs> states = {
2173     {make_hwstate(0.00,0,3,3,&fs[0]),-1,MkSet(97,98,99),0,0,kFTB,false},
2174     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),kBM,kBM,kIdl,false},
2175     {make_hwstate(0.02,0,1,1,&fs[3]),-1,MkSet(91),0,0,kFTB,false},
2176     {make_hwstate(0.03,0,0,0,nullptr),-1,MkSet(),0,0,kTpC,true},
2177     {make_hwstate(0.09,0,0,0,nullptr),.09,MkSet(),kBL,kBL,kIdl,false},
2178   };
2179   run_test(states);
2180   run_test_with_added_resting_thumb(states);
2181   run_test_without_pressure_data(states);
2182 }
2183 
TEST_F(TapToClickStateMachineTest,DoubleTwoFingerTap)2184 TEST_F(TapToClickStateMachineTest, DoubleTwoFingerTap) {
2185   FingerState fs[] = {
2186     {0, 0, 0, 0, 50, 0, 8, 4, 95, 0},
2187     {0, 0, 0, 0, 50, 0, 4, 4, 96, 0},
2188     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2189     {0, 0, 0, 0, 50, 0, 9, 1, 98, 0},
2190   };
2191   std::vector<HWStateGs> states = {
2192     {make_hwstate(0.00, 0, 2, 2, &fs[0]), -1, MkSet(95, 96), 0, 0, kFTB, false},
2193     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), kBR, kBR, kIdl, false},
2194     {make_hwstate(0.02, 0, 2, 2, &fs[2]), -1, MkSet(97, 98), 0, 0, kFTB, false},
2195     {make_hwstate(0.03, 0, 0, 0, nullptr), -1, MkSet(), kBR, kBR, kIdl, false},
2196     {make_hwstate(0.09, 0, 0, 0, nullptr), .09, MkSet(), 0, 0, kIdl, false},
2197   };
2198   run_test(states);
2199   run_test_with_added_resting_thumb(states);
2200   run_test_without_pressure_data(states);
2201 }
2202 
TEST_F(TapToClickStateMachineTest,DrumrollSeparationOnFastSwipe)2203 TEST_F(TapToClickStateMachineTest, DrumrollSeparationOnFastSwipe) {
2204   FingerState fs[] = {
2205     {0, 0, 0, 0, 50, 0, 50, 40, 95, 0},
2206     {0, 0, 0, 0, 50, 0, 70, 40, 96, GESTURES_FINGER_NO_TAP},
2207   };
2208   std::vector<HWStateGs> states = {
2209     {make_hwstate(0.00, 0, 1, 1, &fs[0]), -1, MkSet(95), 0, 0, kFTB, false},
2210     {make_hwstate(0.01, 0, 1, 1, &fs[1]), -1, MkSet(96), 0, 0, kIdl, false},
2211     {make_hwstate(0.02, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
2212   };
2213   run_test(states);
2214   run_test_with_added_resting_thumb(states);
2215   run_test_without_pressure_data(states);
2216 }
2217 
TEST_F(TapToClickStateMachineTest,OneFingerTapThenTwoFingerDrag)2218 TEST_F(TapToClickStateMachineTest, OneFingerTapThenTwoFingerDrag) {
2219   FingerState tap_fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
2220   FingerState drag_fs[] = {
2221     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2222     {0, 0, 0, 0, 50, 0, 9, 1, 98, 0},
2223     {0, 0, 0, 0, 50, 0, 4, 5, 97, 0},
2224     {0, 0, 0, 0, 50, 0, 9, 5, 98, 0},
2225     {0, 0, 0, 0, 50, 0, 4, 9, 97, 0},
2226     {0, 0, 0, 0, 50, 0, 9, 9, 98, 0},
2227   };
2228   std::vector<HWStateGs> states = {
2229     {make_hwstate(0.00,0,1,1,&tap_fs),-1,MkSet(91),0,0,kFTB,false},
2230     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),0,0,kTpC,true},
2231     {make_hwstate(0.02,0,2,2,&drag_fs[0]),-1,MkSet(97,98),kBL,kBL,kFTB,false},
2232     {make_hwstate(0.03,0,2,2,&drag_fs[2]),-1,MkSet(97,98),0,0,kIdl,false},
2233     {make_hwstate(0.04,0,2,2,&drag_fs[4]),-1,MkSet(97,98),0,0,kIdl,false},
2234     {make_hwstate(0.05,0,0,0,nullptr),-1,MkSet(),0,0,kIdl,false},
2235   };
2236   run_test(states);
2237   run_test_with_added_resting_thumb(states);
2238   run_test_without_pressure_data(states);
2239 }
2240 
TEST_F(TapToClickStateMachineTest,OneFingerTapThenMultiFrameTwoFingerDrag)2241 TEST_F(TapToClickStateMachineTest, OneFingerTapThenMultiFrameTwoFingerDrag) {
2242   FingerState tap_fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
2243   FingerState drag_fs[] = {
2244     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2245     {0, 0, 0, 0, 50, 0, 4, 5, 97, 0},
2246     {0, 0, 0, 0, 50, 0, 9, 5, 98, 0},
2247     {0, 0, 0, 0, 50, 0, 4, 9, 97, 0},
2248     {0, 0, 0, 0, 50, 0, 9, 9, 98, 0},
2249   };
2250   std::vector<HWStateGs> states = {
2251     {make_hwstate(0.00,0,1,1,&tap_fs),-1,MkSet(91),0,0,kFTB,false},
2252     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),0,0,kTpC,true},
2253     {make_hwstate(0.02,0,1,1,&drag_fs[0]),-1,MkSet(97),0,0,kSTB,false},
2254     {make_hwstate(0.03,0,2,2,&drag_fs[1]),-1,MkSet(97,98),kBL,kBL,kIdl,false},
2255     {make_hwstate(0.04,0,2,2,&drag_fs[3]),-1,MkSet(97,98),0,0,kIdl,false},
2256     {make_hwstate(0.05,0,0,0,nullptr),-1,MkSet(),0,0,kIdl,false},
2257   };
2258   run_test(states);
2259   run_test_with_added_resting_thumb(states);
2260   run_test_without_pressure_data(states);
2261 }
2262 
TEST_F(TapToClickStateMachineTest,OneFingerTapAndDragWithExtraFingerLater)2263 TEST_F(TapToClickStateMachineTest, OneFingerTapAndDragWithExtraFingerLater) {
2264   FingerState tap_fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
2265   FingerState drag_fs[] = {
2266     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2267     {0, 0, 0, 0, 50, 0, 4, 5, 97, 0},
2268     {0, 0, 0, 0, 50, 0, 9, 5, 98, 0},
2269     {0, 0, 0, 0, 50, 0, 4, 9, 97, 0},
2270     {0, 0, 0, 0, 50, 0, 9, 9, 98, 0},
2271   };
2272   std::vector<HWStateGs> states = {
2273     {make_hwstate(0.00,0,1,1,&tap_fs),-1,MkSet(91),0,0,kFTB,false},
2274     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),0,0,kTpC,true},
2275     {make_hwstate(0.02,0,1,1,&drag_fs[0]),-1,MkSet(97),0,0,kSTB,false},
2276     {make_hwstate(0.13,0,1,1,&drag_fs[0]),-1,MkSet(97),kBL,0,kDrg,false},
2277     {make_hwstate(0.14,0,2,2,&drag_fs[1]),-1,MkSet(97,98),0,kBL,kIdl,false},
2278     {make_hwstate(0.15,0,2,2,&drag_fs[3]),-1,MkSet(97,98),0,0,kIdl,false},
2279     {make_hwstate(0.16,0,0,0,nullptr),-1,MkSet(),0,0,kIdl,false},
2280   };
2281   run_test(states);
2282   run_test_with_added_resting_thumb(states);
2283   run_test_without_pressure_data(states);
2284 }
2285 
TEST_F(TapToClickStateMachineTest,TwoFingerTapThenOneFingerDrag)2286 TEST_F(TapToClickStateMachineTest, TwoFingerTapThenOneFingerDrag) {
2287   FingerState tap_fs[] = {
2288     {0, 0, 0, 0, 50, 0, 4, 9, 97, 0},
2289     {0, 0, 0, 0, 50, 0, 9, 9, 98, 0},
2290   };
2291   FingerState drag_fs[] = {
2292     {0, 0, 0, 0, 50, 0, 4, 4, 95, 0},
2293     {0, 0, 0, 0, 50, 0, 6, 4, 95, 0},
2294     {0, 0, 0, 0, 50, 0, 8, 4, 95, 0},
2295   };
2296   std::vector<HWStateGs> states = {
2297     {make_hwstate(0.00,0,2,2,&tap_fs[0]),-1,MkSet(97,98),0,0,kFTB,false},
2298     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),kBR,kBR,kIdl,false},
2299     {make_hwstate(0.02,0,1,1,&drag_fs[0]),-1,MkSet(95),0,0,kFTB,false},
2300     {make_hwstate(0.03,0,1,1,&drag_fs[1]),-1,MkSet(95),0,0,kIdl,false},
2301     {make_hwstate(0.04,0,1,1,&drag_fs[2]),-1,MkSet(95),0,0,kIdl,false},
2302     {make_hwstate(0.05,0,0,0,nullptr),-1,MkSet(),0,0,kIdl,false},
2303   };
2304   run_test(states);
2305   run_test_with_added_resting_thumb(states);
2306   run_test_without_pressure_data(states);
2307 }
2308 
TEST_F(TapToClickStateMachineTest,TwoFingerTapAndDrag)2309 TEST_F(TapToClickStateMachineTest, TwoFingerTapAndDrag) {
2310   FingerState tap_fs[] = {
2311     {0, 0, 0, 0, 50, 0, 8, 4, 95, 0},
2312     {0, 0, 0, 0, 50, 0, 4, 4, 96, 0},
2313   };
2314   FingerState drag_fs[] = {
2315     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2316     {0, 0, 0, 0, 50, 0, 9, 1, 98, 0},
2317     {0, 0, 0, 0, 50, 0, 4, 5, 97, 0},
2318     {0, 0, 0, 0, 50, 0, 9, 5, 98, 0},
2319     {0, 0, 0, 0, 50, 0, 4, 9, 97, 0},
2320     {0, 0, 0, 0, 50, 0, 9, 9, 98, 0},
2321   };
2322   std::vector<HWStateGs> states = {
2323     {make_hwstate(0.00,0,2,2,&tap_fs[0]),-1,MkSet(95,96),0,0,kFTB,false},
2324     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),kBR,kBR,kIdl,false},
2325     {make_hwstate(0.02,0,2,2,&drag_fs[0]),-1,MkSet(97,98),0,0,kFTB,false},
2326     {make_hwstate(0.03,0,2,2,&drag_fs[2]),-1,MkSet(97,98),0,0,kIdl,false},
2327     {make_hwstate(0.04,0,2,2,&drag_fs[4]),-1,MkSet(97,98),0,0,kIdl,false},
2328     {make_hwstate(0.05,0,0,0,nullptr),-1,MkSet(),0,0,kIdl,false},
2329   };
2330   run_test(states);
2331   run_test_with_added_resting_thumb(states);
2332   run_test_without_pressure_data(states);
2333 }
2334 
TEST_F(TapToClickStateMachineTest,OneFingerDragThenTwoFingerTap)2335 TEST_F(TapToClickStateMachineTest, OneFingerDragThenTwoFingerTap) {
2336   FingerState tap_fs1 = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
2337   FingerState drag_fs[] = {
2338     {0, 0, 0, 0, 50, 0, 4, 4, 95, 0},
2339     {0, 0, 0, 0, 50, 0, 6, 4, 95, 0},
2340     {0, 0, 0, 0, 50, 0, 8, 4, 95, 0},
2341   };
2342   FingerState tap_fs2[] = {
2343     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2344     {0, 0, 0, 0, 50, 0, 9, 1, 98, 0},
2345   };
2346   std::vector<HWStateGs> states = {
2347     {make_hwstate(0.00,0,1,1,&tap_fs1),-1,MkSet(91),0,0,kFTB,false},
2348     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),0,0,kTpC,true},
2349     {make_hwstate(0.02,0,1,1,&drag_fs[0]),-1,MkSet(95),0,0,kSTB,false},
2350     {make_hwstate(0.10,0,1,1,&drag_fs[1]),-1,MkSet(95),kBL,0,kDrg,false},
2351     {make_hwstate(0.11,0,1,1,&drag_fs[2]),-1,MkSet(95),0,0,kDrg,false},
2352     {make_hwstate(0.12,0,0,0,nullptr),-1,MkSet(),0,0,kDRl,true},
2353     {make_hwstate(0.13,0,2,2,&tap_fs2[0]),-1,MkSet(97,98),0,0,kDRt,false},
2354     {make_hwstate(0.14,0,0,0,nullptr),-1,MkSet(),0,kBL,kTpC,true},
2355     {make_hwstate(0.99,0,0,0,nullptr),.99,MkSet(),kBR,kBR,kIdl,false},
2356   };
2357   run_test(states);
2358   run_test_with_added_resting_thumb(states);
2359   run_test_without_pressure_data(states);
2360 }
2361 
TEST_F(TapToClickStateMachineTest,SlowDoubleTap)2362 TEST_F(TapToClickStateMachineTest, SlowDoubleTap) {
2363   FingerState fs[] = {
2364     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2365     {0, 0, 0, 0, 50, 0, 4, 4, 93, 0},
2366   };
2367   std::vector<HWStateGs> states = {
2368     {make_hwstate(0.00, 0, 1, 1, &fs[0]), -1, MkSet(91), 0, 0, kFTB, false},
2369     {make_hwstate(0.10, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kTpC, true},
2370     {make_hwstate(0.12, 0, 1, 1, &fs[1]), -1, MkSet(93), 0, 0, kSTB, false},
2371     {make_hwstate(0.22, 0, 0, 0, nullptr), -1, MkSet(), kBL, kBL, kTpC, true},
2372     {make_hwstate(0.90, 0, 0, 0, nullptr), .9, MkSet(), kBL, kBL, kIdl, false},
2373   };
2374   tap_timeout_ = 0.11;
2375   run_test(states);
2376   run_test_with_added_resting_thumb(states);
2377   run_test_without_pressure_data(states);
2378 }
2379 
TEST_F(TapToClickStateMachineTest,TwoFingerTapWithVeryCloseFingersIgnored)2380 TEST_F(TapToClickStateMachineTest, TwoFingerTapWithVeryCloseFingersIgnored) {
2381   FingerState fs[] = {
2382     {0, 0, 0, 0, 50, 0, 8.0, 4, 95, 0},
2383     {0, 0, 0, 0, 50, 0, 8.1, 4, 96, 0},
2384   };
2385   std::vector<HWStateGs> states = {
2386     {make_hwstate(0.00, 0, 2, 2, &fs[0]), -1, MkSet(95, 96), 0, 0, kIdl, false},
2387     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
2388   };
2389   run_test(states);
2390   run_test_with_added_resting_thumb(states);
2391   run_test_without_pressure_data(states);
2392 }
2393 
TEST_F(TapToClickStateMachineTest,VeryLightTapIgnored)2394 TEST_F(TapToClickStateMachineTest, VeryLightTapIgnored) {
2395   FingerState fs = {0, 0, 0, 0, 15, 0, 9.5, 4, 95, 0};
2396   std::vector<HWStateGs> states = {
2397     {make_hwstate(0.00, 0, 1, 1, &fs), -1, MkSet(95), 0, 0, kFTB, false},
2398     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
2399   };
2400   run_test(states);
2401   run_test_with_added_resting_thumb(states);
2402 }
2403 
TEST_F(TapToClickStateMachineTest,VeryLightTwoFingerTapIgnored)2404 TEST_F(TapToClickStateMachineTest, VeryLightTwoFingerTapIgnored) {
2405   FingerState fs[] = {
2406     {0, 0, 0, 0, 15, 0, 9.5, 4, 95, 0},
2407     {0, 0, 0, 0, 15, 0, 11,  4, 96, 0},
2408   };
2409   std::vector<HWStateGs> states = {
2410     {make_hwstate(0.00, 0, 2, 2, &fs[0]), -1, MkSet(95,96), 0, 0, kFTB, false},
2411     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
2412   };
2413   run_test(states);
2414   run_test_with_added_resting_thumb(states);
2415 }
2416 
TEST_F(TapToClickStateMachineTest,TwoFingerTapWithOneVeryLightGivesRightClick)2417 TEST_F(TapToClickStateMachineTest,
2418        TwoFingerTapWithOneVeryLightGivesRightClick) {
2419   FingerState fs[] = {
2420     {0, 0, 0, 0, 50, 0, 8.1, 4, 96, 0},
2421     {0, 0, 0, 0, 15, 0, 9.5, 4, 95, 0},
2422   };
2423   std::vector<HWStateGs> states = {
2424     {make_hwstate(0.00, 0, 2, 2, &fs[0]), -1, MkSet(95, 96), 0, 0, kFTB, false},
2425     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), kBR, kBR, kIdl, false},
2426   };
2427   run_test(states);
2428   run_test_with_added_resting_thumb(states);
2429 }
2430 
TEST_F(TapToClickStateMachineTest,TwoFingerTapTooFarApartGivesLeftClick)2431 TEST_F(TapToClickStateMachineTest, TwoFingerTapTooFarApartGivesLeftClick) {
2432   FingerState fs[] = {
2433     {0, 0, 0, 0, 50, 0, 20, 4, 95, 0},
2434     {0, 0, 0, 0, 50, 0, 90, 4, 96, 0},
2435   };
2436   std::vector<HWStateGs> states = {
2437     {make_hwstate(0.00, 0, 2, 2, &fs[0]), -1, MkSet(95, 96), 0, 0, kFTB, false},
2438     {make_hwstate(0.01, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kTpC, true},
2439     {make_hwstate(0.07, 0, 0, 0, nullptr), .07, MkSet(), kBL, kBL, kIdl, false},
2440   };
2441   run_test(states);
2442   run_test_with_added_resting_thumb(states);
2443   run_test_without_pressure_data(states);
2444 }
2445 
TEST_F(TapToClickStateMachineTest,TwoFingersMergingDoesntClick)2446 TEST_F(TapToClickStateMachineTest, TwoFingersMergingDoesntClick) {
2447   FingerState fs[] = {
2448     {0, 0, 0, 0, 50, 0, 8, 4, 95, 0},
2449     {0, 0, 0, 0, 50, 0, 4, 4, 96, 0},
2450     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2451   };
2452   std::vector<HWStateGs> states = {
2453     {make_hwstate(0.00, 0, 2, 2, &fs[0]), -1, MkSet(95, 96), 0, 0, kFTB, false},
2454     {make_hwstate(1.00, 0, 2, 2, &fs[0]), -1, MkSet(95, 96), 0, 0, kIdl, false},
2455     {make_hwstate(1.01, 0, 1, 1, &fs[2]), -1, MkSet(91), 0, 0, kIdl, false},
2456     {make_hwstate(1.02, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
2457   };
2458   run_test(states);
2459   run_test_with_added_resting_thumb(states);
2460   run_test_without_pressure_data(states);
2461 }
2462 
TEST_F(TapToClickStateMachineTest,OneFingerMarkedAsPalmIgnored)2463 TEST_F(TapToClickStateMachineTest, OneFingerMarkedAsPalmIgnored) {
2464   FingerState palm_fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, GESTURES_FINGER_PALM};
2465   FingerState fs = {0, 0, 0, 0, 50, 0, 4, 4, 91, 0};
2466   std::vector<HWStateGs> states = {
2467     {make_hwstate(0.00, 0, 1, 1, &palm_fs), -1, MkSet(), 0, 0, kIdl, false},
2468     {make_hwstate(1.50, 0, 1, 1, &fs), -1, MkSet(91), 0, 0, kIdl, false},
2469     {make_hwstate(1.51, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
2470   };
2471   run_test(states);
2472   run_test_with_added_resting_thumb(states);
2473   run_test_without_pressure_data(states);
2474 }
2475 
TEST_F(TapToClickStateMachineTest,TwoFingersBelowPressureThresholdAndNotGesturing)2476 TEST_F(TapToClickStateMachineTest,
2477        TwoFingersBelowPressureThresholdAndNotGesturing) {
2478   // Two fingers seem to tap, the bigger of which is the only one that meets the
2479   // minimum pressure threshold. Then that higher pressure finger is no longer
2480   // gesturing (e.g., it gets classified as a thumb).
2481   // There should be no tap because the one remaining finger didn't meet the
2482   // minimum pressure threshold.
2483   FingerState fs[] = {
2484     {0, 0, 0, 0, 50, 0, 50, 40, 95, 0},
2485     {0, 0, 0, 0, 15, 0, 70, 40, 96, 0},
2486   };
2487   std::vector<HWStateGs> states = {
2488     {make_hwstate(0.00, 0, 2, 2, &fs[0]), -1, MkSet(95, 96), 0, 0, kFTB, false},
2489     {make_hwstate(0.01, 0, 2, 2, &fs[0]), -1, MkSet(96), 0, 0, kFTB, false},
2490     {make_hwstate(0.02, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
2491   };
2492   run_test(states);
2493   run_test_with_added_resting_thumb(states);
2494 }
2495 
TEST_F(TapToClickStateMachineTest,TwoFingerClickNotRegisteredAsTap)2496 TEST_F(TapToClickStateMachineTest, TwoFingerClickNotRegisteredAsTap) {
2497   FingerState fs[] = {
2498     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2499     {0, 0, 0, 0, 75, 0, 4, 9, 92, 0},
2500   };
2501   std::vector<HWStateGs> states = {
2502     {make_hwstate(0.00, 0, 2, 2, &fs[0]), -1, MkSet(91, 92), 0, 0, kFTB, false},
2503     {make_hwstate(0.01, 1, 2, 2, &fs[0]), -1, MkSet(91, 92), 0, 0, kIdl, false},
2504     {make_hwstate(0.02, 0, 2, 2, &fs[0]), -1, MkSet(91, 92), 0, 0, kIdl, false},
2505     {make_hwstate(0.03, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
2506   };
2507   run_test(states);
2508   run_test_with_added_resting_thumb(states);
2509   run_test_without_pressure_data(states);
2510 }
2511 
TEST_F(TapToClickStateMachineTest,T5R2TwoFingerTapWithRestingThumb)2512 TEST_F(TapToClickStateMachineTest, T5R2TwoFingerTapWithRestingThumb) {
2513   FingerState fs[] = {
2514     {0, 0, 0, 0, 80, 0, 5, 9, 70, 0},  // thumb
2515     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2516     {0, 0, 0, 0, 80, 0, 5, 9, 71, 0},  // thumb with new ID
2517   };
2518   std::vector<HWStateGs> states = {
2519     {make_hwstate(0.00, 0, 1, 1, &fs[0]), -1, MkSet(70), 0, 0, kFTB, false},
2520     {make_hwstate(1.00, 0, 1, 1, &fs[0]), -1, MkSet(70), 0, 0, kIdl, false},
2521     {make_hwstate(1.01, 0, 1, 3, &fs[0]), -1, MkSet(70), 0, 0, kFTB, false},
2522     {make_hwstate(1.02, 0, 2, 3, &fs[0]), -1, MkSet(70, 91), 0, 0, kFTB, false},
2523     {make_hwstate(1.03, 0, 0, 2, nullptr), -1, MkSet(), 0, 0, kFTB, false},
2524     {make_hwstate(1.04, 0, 1, 1, &fs[2]), -1, MkSet(71), kBR, kBR, kIdl, false},
2525   };
2526   run_test(states);
2527 }
2528 
TEST_F(TapToClickStateMachineTest,T5R2ThreeFingerTap)2529 TEST_F(TapToClickStateMachineTest, T5R2ThreeFingerTap) {
2530   FingerState fs[] = {
2531     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2532     {0, 0, 0, 0, 75, 0, 4, 9, 92, 0},
2533   };
2534   std::vector<HWStateGs> states = {
2535     {make_hwstate(0.00, 0, 2, 3, &fs[0]), -1, MkSet(91, 92), 0, 0, kFTB, false},
2536     {make_hwstate(0.01, 0, 0, 1, nullptr), -1, MkSet(), 0, 0, kFTB, false},
2537     {make_hwstate(0.02, 0, 0, 0, nullptr), -1, MkSet(), kBM, kBM, kIdl, false},
2538   };
2539   run_test(states);
2540 }
2541 
TEST_F(TapToClickStateMachineTest,T5R2ThreeFingerTap2)2542 TEST_F(TapToClickStateMachineTest, T5R2ThreeFingerTap2) {
2543   // Another three-finger tap test, slightly different to the one above.
2544   FingerState fs[] = {
2545     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2546     {0, 0, 0, 0, 75, 0, 4, 9, 92, 0},
2547   };
2548   std::vector<HWStateGs> states = {
2549     {make_hwstate(0.00, 0, 2, 3, &fs[0]), -1, MkSet(91, 92), 0, 0, kFTB, false},
2550     {make_hwstate(0.01, 0, 2, 3, &fs[0]), -1, MkSet(91, 92), 0, 0, kFTB, false},
2551     {make_hwstate(0.02, 0, 0, 0, nullptr), -1, MkSet(), kBM, kBM, kIdl, false},
2552   };
2553   run_test(states);
2554 }
2555 
TEST_F(TapToClickStateMachineTest,T5R2ThreeFingerTapWithRestingThumb)2556 TEST_F(TapToClickStateMachineTest, T5R2ThreeFingerTapWithRestingThumb) {
2557   FingerState fs[] = {
2558     {0, 0, 0, 0, 80, 0, 5, 9, 70, 0},  // thumb
2559     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2560   };
2561   std::vector<HWStateGs> states = {
2562     {make_hwstate(0.00, 0, 1, 1, &fs[0]), -1, MkSet(70), 0, 0, kFTB, false},
2563     {make_hwstate(1.00, 0, 1, 1, &fs[0]), -1, MkSet(70), 0, 0, kIdl, false},
2564     {make_hwstate(1.01, 0, 1, 4, &fs[0]), -1, MkSet(70), 0, 0, kFTB, false},
2565     {make_hwstate(1.02, 0, 2, 4, &fs[0]), -1, MkSet(70, 91), 0, 0, kFTB, false},
2566     {make_hwstate(1.03, 0, 1, 1, &fs[0]), -1, MkSet(70), kBM, kBM, kIdl, false},
2567   };
2568   run_test(states);
2569 }
2570 
TEST_F(TapToClickStateMachineTest,T5R2FourFingerTap)2571 TEST_F(TapToClickStateMachineTest, T5R2FourFingerTap) {
2572   FingerState fs[] = {
2573     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2574     {0, 0, 0, 0, 75, 0, 4, 9, 92, 0},
2575   };
2576   std::vector<HWStateGs> states = {
2577     {make_hwstate(0.00, 0, 2, 3, &fs[0]), -1, MkSet(91, 92), 0, 0, kFTB, false},
2578     {make_hwstate(0.01, 0, 1, 4, &fs[0]), -1, MkSet(91), 0, 0, kFTB, false},
2579     {make_hwstate(0.02, 0, 2, 4, &fs[0]), -1, MkSet(91, 92), 0, 0, kFTB, false},
2580     {make_hwstate(0.03, 0, 0, 0, nullptr), -1, MkSet(), kBR, kBR, kIdl, false},
2581   };
2582   run_test(states);
2583 }
2584 
TEST_F(TapToClickStateMachineTest,T5R2FourFingerTapWithRestingThumb)2585 TEST_F(TapToClickStateMachineTest, T5R2FourFingerTapWithRestingThumb) {
2586   FingerState thumb_fs = {0, 0, 0, 0, 80, 0, 5, 9, 70, 0};
2587   std::vector<HWStateGs> states = {
2588     {make_hwstate(0.00,0,1,1,&thumb_fs),-1,MkSet(70),0,0,kFTB,false},
2589     {make_hwstate(1.00,0,1,1,&thumb_fs),-1,MkSet(70),0,0,kIdl,false},
2590     {make_hwstate(1.01,0,1,5,&thumb_fs),-1,MkSet(70),0,0,kFTB,false},
2591     {make_hwstate(1.02,0,1,1,&thumb_fs),-1,MkSet(70),kBR,kBR,kIdl,false},
2592   };
2593   run_test(states);
2594 }
2595 
TEST_F(TapToClickStateMachineTest,T5R2FourFingerTapWithRestingThumb2)2596 TEST_F(TapToClickStateMachineTest, T5R2FourFingerTapWithRestingThumb2) {
2597   // Another four-finger tap test, slightly different to the one above.
2598   FingerState fs[] = {
2599     {0, 0, 0, 0, 80, 0, 5, 9, 70, 0},  // thumb
2600     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2601   };
2602   std::vector<HWStateGs> states = {
2603     {make_hwstate(0.00, 0, 1, 1, &fs[0]), -1, MkSet(70), 0, 0, kFTB, false},
2604     {make_hwstate(1.00, 0, 1, 1, &fs[0]), -1, MkSet(70), 0, 0, kIdl, false},
2605     {make_hwstate(1.01, 0, 1, 5, &fs[0]), -1, MkSet(70), 0, 0, kFTB, false},
2606     {make_hwstate(1.02, 0, 2, 5, &fs[0]), -1, MkSet(70, 91), 0, 0, kFTB, false},
2607     {make_hwstate(1.03, 0, 1, 1, &fs[0]), -1, MkSet(70), kBR, kBR, kIdl, false},
2608   };
2609   run_test(states);
2610 }
2611 
TEST_F(TapToClickStateMachineTest,T5R2ThreeFingersLettingGoIgnored)2612 TEST_F(TapToClickStateMachineTest, T5R2ThreeFingersLettingGoIgnored) {
2613   FingerState fs[] = {
2614     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2615     {0, 0, 0, 0, 75, 0, 4, 9, 92, 0},
2616     {0, 0, 0, 0, 50, 0, 4, 1, 97, 0},
2617     {0, 0, 0, 0, 50, 0, 9, 1, 98, 0},
2618   };
2619   std::vector<HWStateGs> states = {
2620     {make_hwstate(0.00, 0, 2, 3, &fs[0]), -1, MkSet(91, 92), 0, 0, kFTB, false},
2621     {make_hwstate(1.01, 0, 2, 3, &fs[0]), -1, MkSet(91, 92), 0, 0, kIdl, false},
2622     {make_hwstate(1.02, 0, 0, 2, nullptr), -1, MkSet(), 0, 0, kIdl, false},
2623     {make_hwstate(1.03, 0, 2, 2, &fs[2]), -1, MkSet(97, 98), 0, 0, kIdl, false},
2624     {make_hwstate(1.04, 0, 0, 0, nullptr), -1, MkSet(), 0, 0, kIdl, false},
2625   };
2626   run_test(states);
2627 }
2628 
2629 namespace {
2630 
2631 struct TapToClickLowPressureBeginOrEndInputs {
2632   stime_t now;
2633   float x0, y0, p0;  // (x, y), pressure
2634   short id0;  // tracking id
2635   float x1, y1, p1;  // (x, y), pressure
2636   short id1;  // tracking id
2637 };
2638 
2639 }  // namespace {}
2640 
2641 // Test that if a tap contact has some frames before and after that tap, with
2642 // a finger that's located far from the tap spot, but has low pressure at that
2643 // location, it's still a tap. We see this happen on some hardware particularly
2644 // for right clicks. This is based on two logs from Ken Moore.
TEST(ImmediateInterpreterTest,TapToClickLowPressureBeginOrEndTest)2645 TEST(ImmediateInterpreterTest, TapToClickLowPressureBeginOrEndTest) {
2646   std::unique_ptr<ImmediateInterpreter> ii;
2647   HardwareProperties hwprops = {
2648     .right = 106.666672,
2649     .bottom = 68.000000,
2650     .res_x = 1,
2651     .res_y = 1,
2652     .orientation_minimum = -1,
2653     .orientation_maximum = 2,
2654     .max_finger_cnt = 15,
2655     .max_touch_cnt = 5,
2656     .supports_t5r2 = 0,
2657     .support_semi_mt = 0,
2658     .is_button_pad = true,
2659     .has_wheel = 0,
2660     .wheel_is_hi_res = 0,
2661     .is_haptic_pad = false,
2662   };
2663   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
2664 
2665   TapToClickLowPressureBeginOrEndInputs inputs[] = {
2666     // Two runs
2667     { 32.4901, 55.5, 24.8,  7.0,  1,  0.0,  0.0,  0.0, -1 },
2668     { 32.5010, 57.7, 25.0, 43.0,  1, 42.0, 27.5, 36.0,  2 },
2669     { 32.5118, 58.0, 25.0, 44.0,  1, 42.0, 27.5, 43.0,  2 },
2670     { 32.5227, 58.0, 25.0, 44.0,  1, 42.0, 27.6, 44.0,  2 },
2671     { 32.5335, 58.0, 25.0, 45.0,  1, 42.0, 27.6, 45.0,  2 },
2672     { 32.5443, 58.0, 25.0, 44.0,  1, 42.0, 27.6, 45.0,  2 },
2673     { 32.5552, 58.0, 25.0, 44.0,  1, 42.0, 27.6, 44.0,  2 },
2674     { 32.5661, 58.0, 25.0, 42.0,  1, 42.0, 27.6, 42.0,  2 },
2675     { 32.5769, 58.0, 25.0, 35.0,  1, 42.0, 27.6, 35.0,  2 },
2676     { 32.5878, 58.0, 25.0, 15.0,  1, 41.9, 27.6, 18.0,  2 },
2677     { 32.5965, 45.9, 27.5,  7.0,  2,  0.0,  0.0,  0.0, -1 },
2678     { 32.6042,  0.0,  0.0,  0.0, -1,  0.0,  0.0,  0.0, -1 },
2679 
2680     { 90.6057, 64.0, 37.0, 18.0,  1,  0.0,  0.0,  0.0, -1 },
2681     { 90.6144, 63.6, 37.0, 43.0,  1,  0.0,  0.0,  0.0, -1 },
2682     { 90.6254, 63.6, 37.0, 43.0,  1, 46.5, 40.2, 47.0,  2 },
2683     { 90.6361, 63.6, 37.0, 44.0,  1, 46.5, 40.2, 44.0,  2 },
2684     { 90.6470, 63.6, 37.0, 45.0,  1, 46.5, 40.2, 46.0,  2 },
2685     { 90.6579, 63.6, 37.0, 45.0,  1, 46.5, 40.2, 46.0,  2 },
2686     { 90.6686, 63.6, 37.0, 45.0,  1, 46.5, 40.2, 47.0,  2 },
2687     { 90.6795, 63.6, 37.0, 46.0,  1, 46.5, 40.2, 47.0,  2 },
2688     { 90.6903, 63.6, 37.0, 45.0,  1, 46.5, 40.2, 46.0,  2 },
2689     { 90.7012, 63.6, 37.0, 44.0,  1, 46.3, 40.2, 44.0,  2 },
2690     { 90.7121, 63.6, 37.2, 38.0,  1, 46.4, 40.2, 31.0,  2 },
2691     { 90.7229, 63.6, 37.4, 22.0,  1, 46.4, 40.2, 12.0,  2 },
2692     { 90.7317, 61.1, 38.0,  8.0,  1,  0.0,  0.0,  0.0, -1 },
2693     { 90.7391,  0.0,  0.0,  0.0, -1,  0.0,  0.0,  0.0, -1 },
2694   };
2695 
2696   bool reset_next_time = true;
2697   for (size_t i = 0; i < arraysize(inputs); i++) {
2698     const TapToClickLowPressureBeginOrEndInputs& input = inputs[i];
2699     if (reset_next_time) {
2700       ii.reset(new ImmediateInterpreter(nullptr, nullptr));
2701       wrapper.Reset(ii.get());
2702       ii->tap_enable_.val_ = 1;
2703       reset_next_time = false;
2704     }
2705     // Prep inputs
2706     FingerState fs[] = {
2707       { 0, 0, 0, 0, input.p0, 0, input.x0, input.y0, input.id0, 0 },
2708       { 0, 0, 0, 0, input.p1, 0, input.x1, input.y1, input.id1, 0 },
2709     };
2710     unsigned short finger_cnt = fs[0].tracking_id == -1 ? 0 :
2711         (fs[1].tracking_id == -1 ? 1 : 2);
2712     HardwareState hs = make_hwstate(input.now, 0, finger_cnt, finger_cnt, fs);
2713     stime_t timeout = NO_DEADLINE;
2714     Gesture* gs = wrapper.SyncInterpret(hs, &timeout);
2715     if (finger_cnt > 0) {
2716       // Expect no timeout
2717       EXPECT_LT(timeout, 0);
2718     } else {
2719       // No timeout b/c it's right click. Expect the right click gesture
2720       ASSERT_NE(nullptr, gs) << "timeout:" << timeout;
2721       EXPECT_EQ(kGestureTypeButtonsChange, gs->type);
2722       EXPECT_EQ(GESTURES_BUTTON_RIGHT, gs->details.buttons.down);
2723       EXPECT_EQ(GESTURES_BUTTON_RIGHT, gs->details.buttons.up);
2724       reset_next_time = true;  // All done w/ this run.
2725     }
2726   }
2727 }
2728 
2729 // Does two tap gestures, one with keyboard interference.
TEST(ImmediateInterpreterTest,TapToClickKeyboardTest)2730 TEST(ImmediateInterpreterTest, TapToClickKeyboardTest) {
2731   std::unique_ptr<ImmediateInterpreter> ii;
2732 
2733   HardwareProperties hwprops = {
2734     .right = 200,
2735     .bottom = 200,
2736     .res_x = 1.0,
2737     .res_y = 1.0,
2738     .orientation_minimum = -1,
2739     .orientation_maximum = 2,
2740     .max_finger_cnt = 5,
2741     .max_touch_cnt = 5,
2742     .supports_t5r2 = 0,
2743     .support_semi_mt = 0,
2744     .is_button_pad = 1,
2745     .has_wheel = 0,
2746     .wheel_is_hi_res = 0,
2747     .is_haptic_pad = 0,
2748   };
2749   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
2750 
2751   FingerState fs = {
2752     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
2753     0, 0, 0, 0, 50, 0, 4, 4, 91, 0
2754   };
2755   HardwareState hwstates[] = {
2756     // Simple 1-finger tap
2757     make_hwstate(0.01, 0, 1, 1, &fs),
2758     make_hwstate(0.02, 0, 0, 0, nullptr),
2759     make_hwstate(0.30, 0, 0, 0, nullptr),
2760   };
2761 
2762   enum {
2763     kWithoutKeyboard = 0,
2764     kWithKeyboard,
2765     kMaxTests
2766   };
2767   for (size_t test = 0; test != kMaxTests; test++) {
2768     ii.reset(new ImmediateInterpreter(nullptr, nullptr));
2769     wrapper.Reset(ii.get());
2770     ii->motion_tap_prevent_timeout_.val_ = 0;
2771     ii->tap_enable_.val_ = 1;
2772     ii->tap_drag_enable_.val_ = 1;
2773 
2774     if (test == kWithKeyboard)
2775       ii->keyboard_touched_ = 0.001;
2776 
2777     unsigned down = 0;
2778     unsigned up = 0;
2779     for (size_t i = 0; i < arraysize(hwstates); i++) {
2780       down = 0;
2781       up = 0;
2782       stime_t timeout = NO_DEADLINE;
2783       std::set<short> gs =
2784           hwstates[i].finger_cnt == 1 ? MkSet(91) : MkSet();
2785       ii->metrics_->Update(hwstates[i]);
2786       ii->UpdateTapState(
2787           &hwstates[i],
2788           gs,
2789           false,  // same fingers
2790           hwstates[i].timestamp,
2791           &down,
2792           &up,
2793           &timeout);
2794     }
2795     EXPECT_EQ(down, up);
2796     if (test == kWithoutKeyboard)
2797       EXPECT_EQ(GESTURES_BUTTON_LEFT, down);
2798     else
2799       EXPECT_EQ(0, down);
2800   }
2801 }
2802 
2803 enum class TtcEnableTestMode {
2804   TapEnabled = 0,
2805   TapDisabledDuringGesture,
2806   TapDisabledBeforeGestureWhileIdle,
2807   TapPausedDuringGesture,
2808   TapPausedBeforeGestureWhileIdle,
2809 };
2810 
2811 class ImmediateInterpreterTtcEnableTest :
2812           public testing::TestWithParam<TtcEnableTestMode> {};
2813 
TEST_P(ImmediateInterpreterTtcEnableTest,TapToClickEnableTest)2814 TEST_P(ImmediateInterpreterTtcEnableTest, TapToClickEnableTest) {
2815   ImmediateInterpreter ii(nullptr, nullptr);
2816   ii.drag_lock_enable_.val_ = 1;
2817   ii.motion_tap_prevent_timeout_.val_ = 0;
2818   ii.tap_drag_timeout_.val_ = 0.05;
2819   ii.tap_enable_.val_ = 1;
2820   ii.tap_drag_enable_.val_ = 1;
2821   ii.tap_paused_.val_ = 0;
2822   ii.tap_move_dist_.val_ = 1.0;
2823   ii.tap_timeout_.val_ = 0.05;
2824   EXPECT_EQ(kIdl, ii.tap_to_click_state_);
2825   EXPECT_TRUE(ii.tap_enable_.val_);
2826 
2827   HardwareProperties hwprops = {
2828     .right = 200,
2829     .bottom = 200,
2830     .res_x = 1.0,
2831     .res_y = 1.0,
2832     .orientation_minimum = -1,
2833     .orientation_maximum = 2,
2834     .max_finger_cnt = 5,
2835     .max_touch_cnt = 5,
2836     .supports_t5r2 = 0,
2837     .support_semi_mt = 0,
2838     .is_button_pad = 1,
2839     .has_wheel = 0,
2840     .wheel_is_hi_res = 0,
2841     .is_haptic_pad = 0,
2842   };
2843   TestInterpreterWrapper wrapper(&ii, &hwprops);
2844 
2845   FingerState fs[] = {
2846     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
2847     {0, 0, 0, 0, 50, 0, 4, 4, 91, 0},
2848     {0, 0, 0, 0, 50, 0, 4, 4, 92, 0},
2849     {0, 0, 0, 0, 50, 0, 6, 4, 92, 0},
2850     {0, 0, 0, 0, 50, 0, 8, 4, 92, 0},
2851     {0, 0, 0, 0, 50, 0, 4, 4, 93, 0},
2852     {0, 0, 0, 0, 50, 0, 6, 4, 93, 0},
2853     {0, 0, 0, 0, 50, 0, 8, 4, 93, 0},
2854   };
2855 
2856   HWStateGs hwsgs_list[] = {
2857     // 1-finger tap, move, release, move again (drag lock)
2858     {make_hwstate(0.00,0,1,1,&fs[0]),-1,MkSet(91),0,0,kFTB,false},
2859     {make_hwstate(0.01,0,0,0,nullptr),-1,MkSet(),0,0,kTpC,true},
2860     {make_hwstate(0.02,0,1,1,&fs[1]),-1,MkSet(92),0,0,kSTB,false},
2861     {make_hwstate(0.08,0,1,1,&fs[2]),-1,MkSet(92),kBL,0,kDrg,false},
2862     {make_hwstate(0.09,0,1,1,&fs[3]),-1,MkSet(92),0,0,kDrg,false},
2863     {make_hwstate(0.10,0,0,0,nullptr),-1,MkSet(),0,0,kDRl,true},
2864     {make_hwstate(0.11,0,1,1,&fs[4]),-1,MkSet(93),0,0,kDRt,false},
2865     {make_hwstate(0.12,0,1,1,&fs[5]),-1,MkSet(93),0,0,kDrg,false},
2866     {make_hwstate(0.13,0,1,1,&fs[6]),-1,MkSet(93),0,0,kDrg,false},
2867     {make_hwstate(0.14,0,0,0,nullptr),-1,MkSet(),0,0,kDRl,true},
2868     {make_hwstate(0.99,0,0,0,nullptr),.99,MkSet(),0,kBL,kIdl,false}
2869   };
2870 
2871   for (size_t i = 0; i < arraysize(hwsgs_list); ++i) {
2872     string desc;
2873     stime_t disable_time = 0.0;
2874     stime_t pause_time = 0.0;
2875     switch (GetParam()) {
2876       case TtcEnableTestMode::TapEnabled:
2877         desc = "tap enabled";
2878         disable_time = -1;  // unreachable time
2879         pause_time = -1;
2880         break;
2881       case TtcEnableTestMode::TapDisabledDuringGesture:
2882         desc = "tap disabled during gesture";
2883         disable_time = 0.02;
2884         pause_time = -1;
2885         break;
2886       case TtcEnableTestMode::TapDisabledBeforeGestureWhileIdle:
2887         desc = "tap disabled while Idle";
2888         disable_time = 0.00;
2889         pause_time = -1;
2890         break;
2891       case TtcEnableTestMode::TapPausedDuringGesture:
2892         desc = "tap paused during gesture";
2893         disable_time = -1;
2894         pause_time = 0.02;
2895         break;
2896       case TtcEnableTestMode::TapPausedBeforeGestureWhileIdle:
2897         desc = "tap paused while Idle";
2898         disable_time = 0.00;
2899         pause_time = -1;
2900         break;
2901     }
2902     SCOPED_TRACE(StringPrintf("State %zu (%s)", i, desc.c_str()));
2903 
2904     HWStateGs &hwsgs = hwsgs_list[i];
2905     HardwareState* hwstate = &hwsgs.hws;
2906     stime_t now = hwsgs.callback_now;
2907     if (hwsgs.callback_now >= 0.0)
2908       hwstate = nullptr;
2909     else
2910       now = hwsgs.hws.timestamp;
2911 
2912     bool same_fingers = false;
2913     if (!hwstate || hwstate->timestamp != 0.0) {
2914       same_fingers = ii.state_buffer_.Get(1).SameFingersAs(hwsgs.hws);
2915     }
2916 
2917     // Disable tap in the middle of the gesture
2918     if (hwstate && hwstate->timestamp == disable_time)
2919       ii.tap_enable_.val_ = 0;
2920 
2921     if (hwstate && hwstate->timestamp == pause_time)
2922       ii.tap_paused_.val_ = true;
2923 
2924     if (hwstate) {
2925       ii.metrics_->Update(*hwstate);
2926       ii.state_buffer_.PushState(*hwstate);
2927     }
2928     unsigned buttons_down = 0;
2929     unsigned buttons_up = 0;
2930     stime_t timeout = NO_DEADLINE;
2931     ii.UpdateTapState(
2932         hwstate, hwsgs.gesturing_fingers, same_fingers, now, &buttons_down,
2933         &buttons_up, &timeout);
2934     ii.prev_gs_fingers_ = hwsgs.gesturing_fingers;
2935 
2936     switch (GetParam()) {
2937       case TtcEnableTestMode::TapEnabled:
2938       case TtcEnableTestMode::TapDisabledDuringGesture:
2939       case TtcEnableTestMode::TapPausedDuringGesture:
2940         // tap should be enabled
2941         EXPECT_EQ(hwsgs.expected_down, buttons_down);
2942         EXPECT_EQ(hwsgs.expected_up, buttons_up);
2943         if (hwsgs.timeout)
2944           EXPECT_GT(timeout, 0.0);
2945         else
2946           EXPECT_DOUBLE_EQ(NO_DEADLINE, timeout);
2947         EXPECT_EQ(hwsgs.expected_state, ii.tap_to_click_state_);
2948         break;
2949       case TtcEnableTestMode::TapDisabledBeforeGestureWhileIdle:
2950       case TtcEnableTestMode::TapPausedBeforeGestureWhileIdle:
2951         // tap should be disabled
2952         EXPECT_EQ(0, buttons_down);
2953         EXPECT_EQ(0, buttons_up);
2954         EXPECT_DOUBLE_EQ(NO_DEADLINE, timeout);
2955         EXPECT_EQ(kIdl, ii.tap_to_click_state_);
2956         break;
2957     }
2958   }
2959 }
2960 
2961 INSTANTIATE_TEST_SUITE_P(
2962     ImmediateInterpreterTtc, ImmediateInterpreterTtcEnableTest,
2963     testing::Values(TtcEnableTestMode::TapEnabled,
2964                     TtcEnableTestMode::TapDisabledDuringGesture,
2965                     TtcEnableTestMode::TapDisabledBeforeGestureWhileIdle,
2966                     TtcEnableTestMode::TapPausedDuringGesture,
2967                     TtcEnableTestMode::TapPausedBeforeGestureWhileIdle));
2968 
2969 struct ClickTestHardwareStateAndExpectations {
2970   HardwareState hs;
2971   stime_t timeout;
2972   unsigned expected_down;
2973   unsigned expected_up;
2974 };
2975 
TEST(ImmediateInterpreterTest,ClickTest)2976 TEST(ImmediateInterpreterTest, ClickTest) {
2977   ImmediateInterpreter ii(nullptr, nullptr);
2978   HardwareProperties hwprops = {
2979     .right = 100,
2980     .bottom = 100,
2981     .res_x = 1,
2982     .res_y = 1,
2983     .orientation_minimum = -1,
2984     .orientation_maximum = 2,
2985     .max_finger_cnt = 2,
2986     .max_touch_cnt = 5,
2987     .supports_t5r2 = 0,
2988     .support_semi_mt = 0,
2989     .is_button_pad = 1,
2990     .has_wheel = 0,
2991     .wheel_is_hi_res = 0,
2992     .is_haptic_pad = 0,
2993   };
2994   TestInterpreterWrapper wrapper(&ii, &hwprops);
2995   EXPECT_FLOAT_EQ(10.0, ii.tapping_finger_min_separation_.val_);
2996 
2997   FingerState finger_states[] = {
2998     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
2999     {0, 0, 0, 0, 10, 0, 50, 50, 1, 0},
3000     {0, 0, 0, 0, 10, 0, 70, 50, 2, 0},
3001     // Fingers very close together - shouldn't right click
3002     {0, 0, 0, 0, 10, 0, 50, 50, 1, 0},
3003     {0, 0, 0, 0, 10, 0, 55, 50, 2, 0},
3004     // Large vertical dist - shouldn right click when timing is good.
3005     {0, 0, 0, 0, 10, 0,  8.4, 94, 1, 0},
3006     {0, 0, 0, 0, 10, 0, 51.2, 70, 2, 0},
3007   };
3008   ClickTestHardwareStateAndExpectations records[] = {
3009     // reset
3010     {make_hwstate(0,0,0,0,nullptr),NO_DEADLINE,0,0},
3011 
3012     // button down, 2 fingers touch, button up, 2 fingers lift
3013     {make_hwstate(1,1,0,0,nullptr),NO_DEADLINE,0,0},
3014     {make_hwstate(1.01,1,2,2,&finger_states[0]), NO_DEADLINE, 0, 0},
3015     {make_hwstate(2,0,2,2,&finger_states[0]),
3016      NO_DEADLINE, GESTURES_BUTTON_RIGHT, GESTURES_BUTTON_RIGHT},
3017     {make_hwstate(3,0,0,0,nullptr), NO_DEADLINE, 0, 0},
3018 
3019     // button down, 2 close fingers touch, fingers lift
3020     {make_hwstate(7,1,0,0,nullptr), NO_DEADLINE, 0, 0},
3021     {make_hwstate(7.01,1,2,2,&finger_states[2]), NO_DEADLINE, 0, 0},
3022     {make_hwstate(7.02,0,2,2,&finger_states[2]),
3023      NO_DEADLINE, GESTURES_BUTTON_LEFT,GESTURES_BUTTON_LEFT},
3024     {make_hwstate(8,0,0,0,nullptr), NO_DEADLINE, 0, 0},
3025 
3026     // button down with 2 fingers, button up, fingers lift
3027     {make_hwstate(9.01,1,2,2,&finger_states[4]),NO_DEADLINE,0,0},
3028     {make_hwstate(9.02,1,2,2,&finger_states[4]),NO_DEADLINE,0,0},
3029     {make_hwstate(9.5,0,2,2,&finger_states[4]),
3030      NO_DEADLINE, GESTURES_BUTTON_RIGHT,GESTURES_BUTTON_RIGHT},
3031     {make_hwstate(10,0,0,0,nullptr), NO_DEADLINE, 0, 0},
3032 
3033     // button down with 2 fingers, timeout, button up, fingers lift
3034     {make_hwstate(11,1,2,2,&finger_states[4]), NO_DEADLINE, 0, 0},
3035     {make_hwstate(0,0,0,0,nullptr),11.5,GESTURES_BUTTON_RIGHT,0},
3036     {make_hwstate(12,0,2,2,&finger_states[4]), NO_DEADLINE, 0,
3037      GESTURES_BUTTON_RIGHT},
3038     {make_hwstate(10,0,0,0,nullptr), NO_DEADLINE, 0, 0}
3039   };
3040 
3041   for (size_t i = 0; i < arraysize(records); ++i) {
3042     Gesture* result = nullptr;
3043     if (records[i].timeout < 0.0)
3044       result = wrapper.SyncInterpret(records[i].hs, nullptr);
3045     else
3046       result = wrapper.HandleTimer(records[i].timeout, nullptr);
3047     if (records[i].expected_down == 0 && records[i].expected_up == 0) {
3048       EXPECT_EQ(nullptr, result) << "i=" << i;
3049     } else {
3050       ASSERT_NE(nullptr, result) << "i=" << i;
3051       EXPECT_EQ(records[i].expected_down, result->details.buttons.down);
3052       EXPECT_EQ(records[i].expected_up, result->details.buttons.up);
3053     }
3054   }
3055 }
3056 
3057 struct ClickDragLockInputAndExpectations {
3058   HardwareState hs;
3059   stime_t timeout;
3060   unsigned expected_down;
3061   unsigned expected_up;
3062   bool expected_move;
3063 };
3064 
TEST(ImmediateInterpreterTest,ClickDragLockTest)3065 TEST(ImmediateInterpreterTest, ClickDragLockTest) {
3066   ImmediateInterpreter ii(nullptr, nullptr);
3067   HardwareProperties hwprops = {
3068     .right = 100,
3069     .bottom = 100,
3070     .res_x = 1,
3071     .res_y = 1,
3072     .orientation_minimum = -1,
3073     .orientation_maximum = 2,
3074     .max_finger_cnt = 2,
3075     .max_touch_cnt = 5,
3076     .supports_t5r2 = 0,
3077     .support_semi_mt = 0,
3078     .is_button_pad = 1,
3079     .has_wheel = 0,
3080     .wheel_is_hi_res = 0,
3081     .is_haptic_pad = 0,
3082   };
3083   TestInterpreterWrapper wrapper(&ii, &hwprops);
3084 
3085   FingerState finger_states[] = {
3086     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
3087     {0, 0, 0, 0, 10, 0, 50, 50, 1, 0},
3088     {0, 0, 0, 0, 10, 0, 70, 50, 2, 0},
3089     // One finger moves fast enough to lock on.
3090     {0, 0, 0, 0, 10, 0, 45, 50, 1, 0},
3091     {0, 0, 0, 0, 10, 0, 70, 50, 2, 0},
3092     // Second finger moves, but not fast enough to break lock.
3093     {0, 0, 0, 0, 10, 0, 45, 50, 1, 0},
3094     {0, 0, 0, 0, 10, 0, 71, 50, 2, 0},
3095     // Second finger moves fast enough to break lock.
3096     {0, 0, 0, 0, 10, 0, 45, 50, 1, 0},
3097     {0, 0, 0, 0, 10, 0, 76, 50, 2, 0},
3098     // First finger moves, but not fast enough to break lock.
3099     {0, 0, 0, 0, 10, 0, 44, 50, 1, 0},
3100     {0, 0, 0, 0, 10, 0, 76, 50, 2, 0},
3101   };
3102   ClickDragLockInputAndExpectations records[] = {
3103     // reset
3104     {make_hwstate(0,0,0,0,nullptr),NO_DEADLINE,0,0,false},
3105 
3106     {make_hwstate(1,1,0,0,nullptr),NO_DEADLINE,0,0,false},
3107     {make_hwstate(1.01,1,2,2,&finger_states[0]), NO_DEADLINE, 0, 0, false},
3108     {make_hwstate(2,1,2,2,&finger_states[0]),
3109      NO_DEADLINE, GESTURES_BUTTON_RIGHT, 0, false},
3110     {make_hwstate(2.1,1,2,2,&finger_states[2]), NO_DEADLINE, 0, 0, true},
3111     {make_hwstate(2.2,1,2,2,&finger_states[4]), NO_DEADLINE, 0, 0, false},
3112     {make_hwstate(2.3,1,2,2,&finger_states[6]), NO_DEADLINE, 0, 0, true},
3113     {make_hwstate(2.4,1,2,2,&finger_states[8]), NO_DEADLINE, 0, 0, false},
3114     {make_hwstate(3,0,0,0,nullptr),
3115      NO_DEADLINE, 0, GESTURES_BUTTON_RIGHT, false},
3116 
3117     {make_hwstate(10,0,0,0,nullptr), NO_DEADLINE, 0, 0, false}
3118   };
3119 
3120   for (size_t i = 0; i < arraysize(records); ++i) {
3121     Gesture* result = nullptr;
3122     if (records[i].timeout < 0.0)
3123       result = wrapper.SyncInterpret(records[i].hs, nullptr);
3124     else
3125       result = wrapper.HandleTimer(records[i].timeout, nullptr);
3126     if (records[i].expected_move) {
3127       ASSERT_NE(nullptr, result) << "i=" << i;
3128       EXPECT_EQ(result->type, kGestureTypeMove);
3129       EXPECT_NE(result->details.move.dx, 0.0);
3130     } else if (records[i].expected_down != 0 || records[i].expected_up != 0) {
3131       ASSERT_NE(nullptr, result) << "i=" << i;
3132       EXPECT_EQ(records[i].expected_down, result->details.buttons.down);
3133       EXPECT_EQ(records[i].expected_up, result->details.buttons.up);
3134     } else {
3135       if (result) {
3136         EXPECT_EQ(result->type, kGestureTypeMove);
3137         EXPECT_EQ(result->details.move.dx, 0.0);
3138       }
3139     }
3140   }
3141 }
3142 
3143 struct BigHandsRightClickInputAndExpectations {
3144   HardwareState hs;
3145   unsigned out_buttons_down;
3146   unsigned out_buttons_up;
3147   FingerState fs[2];
3148 };
3149 
3150 // This was recorded from Ian Fette, who had trouble right-clicking.
3151 // This test plays back part of his log to ensure that it generates a
3152 // right click.
TEST(ImmediateInterpreterTest,BigHandsRightClickTest)3153 TEST(ImmediateInterpreterTest, BigHandsRightClickTest) {
3154   HardwareProperties hwprops = {
3155     .right = 106.666672,
3156     .bottom = 68.000000,
3157     .res_x = 1,
3158     .res_y = 1,
3159     .orientation_minimum = -1,
3160     .orientation_maximum = 2,
3161     .max_finger_cnt = 15,
3162     .max_touch_cnt = 5,
3163     .supports_t5r2 = 0,
3164     .support_semi_mt = 0,
3165     .is_button_pad = true,
3166     .has_wheel = 0,
3167     .wheel_is_hi_res = 0,
3168     .is_haptic_pad = false,
3169   };
3170   BigHandsRightClickInputAndExpectations records[] = {
3171     { make_hwstate(1329527921.327647, 0, 2, 2, nullptr), 0, 0,
3172       { { 0, 0, 0, 0, 50.013428, 0, 20.250002, 59.400002, 130, 0 },
3173         { 0, 0, 0, 0, 41.862095, 0, 57.458694, 43.700001, 131, 0 } } },
3174     { make_hwstate(1329527921.344421, 0, 2, 2, nullptr), 0, 0,
3175       { { 0, 0, 0, 0, 50.301102, 0, 20.250002, 59.400002, 130, 0 },
3176         { 0, 0, 0, 0, 42.007469, 0, 57.479977, 43.700001, 131, 0 } } },
3177     { make_hwstate(1329527921.361196, 1, 2, 2, nullptr), 0, 0,
3178       { { 0, 0, 0, 0, 50.608433, 0, 20.250002, 59.400002, 130, 0 },
3179         { 0, 0, 0, 0, 42.065464, 0, 57.494164, 43.700001, 131, 0 } } },
3180     { make_hwstate(1329527921.372364, 1, 2, 2, nullptr), 0, 0,
3181       { { 0, 0, 0, 0, 50.840954, 0, 20.250002, 59.400002, 130, 0 },
3182         { 0, 0, 0, 0, 42.071739, 0, 57.507217, 43.700001, 131, 0 } } },
3183     { make_hwstate(1329527921.383517, 1, 2, 2, nullptr), 0, 0,
3184       { { 0, 0, 0, 0, 51.047310, 0, 20.250002, 59.400002, 130, 0 },
3185         { 0, 0, 0, 0, 42.054974, 0, 57.527523, 43.700001, 131, 0 } } },
3186     { make_hwstate(1329527921.394680, 1, 2, 2, nullptr), 0, 0,
3187       { { 0, 0, 0, 0, 51.355824, 0, 20.250002, 59.400002, 130, 0 },
3188         { 0, 0, 0, 0, 42.066948, 0, 57.550964, 43.700001, 131, 0 } } },
3189     { make_hwstate(1329527921.405842, 1, 2, 2, nullptr), 0, 0,
3190       { { 0, 0, 0, 0, 51.791901, 0, 20.250002, 59.400002, 130, 0 },
3191         { 0, 0, 0, 0, 42.188736, 0, 57.569374, 43.700001, 131, 0 } } },
3192     { make_hwstate(1329527921.416791, 1, 2, 2, nullptr), GESTURES_BUTTON_RIGHT,
3193       0,
3194       { { 0, 0, 0, 0, 52.264156, 0, 20.250002, 59.400002, 130, 0 },
3195         { 0, 0, 0, 0, 42.424179, 0, 57.586361, 43.700001, 131, 0 } } },
3196     { make_hwstate(1329527921.427937, 1, 2, 2, nullptr), 0, 0,
3197       { { 0, 0, 0, 0, 52.725105, 0, 20.250002, 59.400002, 130, 0 },
3198         { 0, 0, 0, 0, 42.676739, 0, 57.609421, 43.700001, 131, 0 } } },
3199     { make_hwstate(1329527921.439094, 1, 2, 2, nullptr), 0, 0,
3200       { { 0, 0, 0, 0, 53.191925, 0, 20.250002, 59.400002, 130, 0 },
3201         { 0, 0, 0, 0, 42.868217, 0, 57.640007, 43.700001, 131, 0 } } },
3202     { make_hwstate(1329527921.461392, 1, 2, 2, nullptr), 0, 0,
3203       { { 0, 0, 0, 0, 53.602665, 0, 20.250002, 59.400002, 130, 0 },
3204         { 0, 0, 0, 0, 43.016544, 0, 57.676689, 43.700001, 131, 0 } } },
3205     { make_hwstate(1329527921.483690, 1, 2, 2, nullptr), 0, 0,
3206       { { 0, 0, 0, 0, 53.879429, 0, 20.250002, 59.400002, 130, 0 },
3207         { 0, 0, 0, 0, 43.208221, 0, 57.711613, 43.700001, 131, 0 } } },
3208     { make_hwstate(1329527921.511815, 1, 2, 2, nullptr), 0, 0,
3209       { { 0, 0, 0, 0, 54.059937, 0, 20.250002, 59.400002, 130, 0 },
3210         { 0, 0, 0, 0, 43.467258, 0, 57.736385, 43.700001, 131, 0 } } },
3211     { make_hwstate(1329527921.539940, 1, 2, 2, nullptr), 0, 0,
3212       { { 0, 0, 0, 0, 54.253189, 0, 20.250002, 59.400002, 130, 0 },
3213         { 0, 0, 0, 0, 43.717934, 0, 57.750286, 43.700001, 131, 0 } } },
3214     { make_hwstate(1329527921.556732, 1, 2, 2, nullptr), 0, 0,
3215       { { 0, 0, 0, 0, 54.500740, 0, 20.250002, 59.400002, 130, 0 },
3216         { 0, 0, 0, 0, 43.863792, 0, 57.758759, 43.700001, 131, 0 } } },
3217     { make_hwstate(1329527921.573523, 1, 2, 2, nullptr), 0, 0,
3218       { { 0, 0, 0, 0, 54.737640, 0, 20.250002, 59.400002, 130, 0 },
3219         { 0, 0, 0, 0, 43.825844, 0, 57.771137, 43.700001, 131, 0 } } },
3220     { make_hwstate(1329527921.584697, 1, 2, 2, nullptr), 0, 0,
3221       { { 0, 0, 0, 0, 54.906223, 0, 20.250002, 59.400002, 130, 0 },
3222         { 0, 0, 0, 0, 43.654804, 0, 57.790218, 43.700001, 131, 0 } } },
3223     { make_hwstate(1329527921.595872, 1, 2, 2, nullptr), 0, 0,
3224       { { 0, 0, 0, 0, 55.001118, 0, 20.250002, 59.400002, 130, 0 },
3225         { 0, 0, 0, 0, 43.542431, 0, 57.809731, 43.700001, 131, 0 } } },
3226     { make_hwstate(1329527921.618320, 1, 2, 2, nullptr), 0, 0,
3227       { { 0, 0, 0, 0, 55.039989, 0, 20.252811, 59.400002, 130, 0 },
3228         { 0, 0, 0, 0, 43.585777, 0, 57.824154, 43.700001, 131, 0 } } },
3229     { make_hwstate(1329527921.640768, 1, 2, 2, nullptr), 0, 0,
3230       { { 0, 0, 0, 0, 55.045246, 0, 20.264456, 59.400002, 130, 0 },
3231         { 0, 0, 0, 0, 43.715435, 0, 57.832584, 43.700001, 131, 0 } } },
3232     { make_hwstate(1329527921.691161, 1, 2, 2, nullptr), 0, 0,
3233       { { 0, 0, 0, 0, 55.068935, 0, 20.285036, 59.400002, 130, 0 },
3234         { 0, 0, 0, 0, 43.845741, 0, 57.836266, 43.700001, 131, 0 } } },
3235     { make_hwstate(1329527921.741554, 1, 2, 2, nullptr), 0, 0,
3236       { { 0, 0, 0, 0, 55.195026, 0, 20.306564, 59.400002, 130, 0 },
3237         { 0, 0, 0, 0, 43.941154, 0, 57.836994, 43.700001, 131, 0 } } },
3238     { make_hwstate(1329527921.758389, 1, 2, 2, nullptr), 0, 0,
3239       { { 0, 0, 0, 0, 55.430550, 0, 20.322674, 59.400002, 130, 0 },
3240         { 0, 0, 0, 0, 43.962692, 0, 57.836308, 43.700001, 131, 0 } } },
3241     { make_hwstate(1329527921.775225, 1, 2, 2, nullptr), 0, 0,
3242       { { 0, 0, 0, 0, 55.681423, 0, 20.332201, 59.400002, 130, 0 },
3243         { 0, 0, 0, 0, 43.846741, 0, 57.835224, 43.700001, 131, 0 } } },
3244     { make_hwstate(1329527921.786418, 1, 2, 2, nullptr), 0, 0,
3245       { { 0, 0, 0, 0, 55.803486, 0, 20.336439, 59.400002, 130, 0 },
3246         { 0, 0, 0, 0, 43.604134, 0, 57.834267, 43.700001, 131, 0 } } },
3247     { make_hwstate(1329527921.803205, 1, 2, 2, nullptr), 0, 0,
3248       { { 0, 0, 0, 0, 55.738258, 0, 20.337351, 59.396629, 130, 0 },
3249         { 0, 0, 0, 0, 43.340977, 0, 57.833622, 43.700001, 131, 0 } } },
3250     { make_hwstate(1329527921.819993, 1, 2, 2, nullptr), 0, 0,
3251       { { 0, 0, 0, 0, 55.647045, 0, 20.336643, 59.382656, 130, 0 },
3252         { 0, 0, 0, 0, 43.140343, 0, 57.833279, 43.700001, 131, 0 } } },
3253     { make_hwstate(1329527921.831121, 1, 2, 2, nullptr), 0, 0,
3254       { { 0, 0, 0, 0, 55.670898, 0, 20.335459, 59.357960, 130, 0 },
3255         { 0, 0, 0, 0, 43.019653, 0, 57.827530, 43.700001, 131, 0 } } },
3256     { make_hwstate(1329527921.842232, 1, 2, 2, nullptr), 0, 0,
3257       { { 0, 0, 0, 0, 55.769543, 0, 20.334396, 59.332127, 130, 0 },
3258         { 0, 0, 0, 0, 42.964531, 0, 57.807049, 43.700001, 131, 0 } } },
3259     { make_hwstate(1329527921.853342, 1, 2, 2, nullptr), 0, 0,
3260       { { 0, 0, 0, 0, 55.872444, 0, 20.333672, 59.312794, 130, 0 },
3261         { 0, 0, 0, 0, 42.951347, 0, 57.771957, 43.700001, 131, 0 } } },
3262     { make_hwstate(1329527921.864522, 1, 2, 2, nullptr), 0, 0,
3263       { { 0, 0, 0, 0, 55.949341, 0, 20.333281, 59.301361, 130, 0 },
3264         { 0, 0, 0, 0, 42.959034, 0, 57.729061, 43.700001, 131, 0 } } },
3265     { make_hwstate(1329527921.875702, 1, 2, 2, nullptr), 0, 0,
3266       { { 0, 0, 0, 0, 55.994751, 0, 20.333134, 59.296276, 130, 0 },
3267         { 0, 0, 0, 0, 42.973259, 0, 57.683277, 43.700001, 131, 0 } } },
3268     { make_hwstate(1329527921.886840, 1, 2, 2, nullptr), 0, 0,
3269       { { 0, 0, 0, 0, 56.014912, 0, 20.333128, 59.295181, 130, 0 },
3270         { 0, 0, 0, 0, 42.918892, 0, 57.640221, 43.700001, 131, 0 } } },
3271     { make_hwstate(1329527921.898031, 1, 2, 2, nullptr), 0, 0,
3272       { { 0, 0, 0, 0, 55.951756, 0, 20.333181, 59.296028, 130, 0 },
3273         { 0, 0, 0, 0, 42.715969, 0, 57.601479, 43.700001, 131, 0 } } },
3274     { make_hwstate(1329527921.909149, 1, 2, 2, nullptr), 0, 0,
3275       { { 0, 0, 0, 0, 55.736336, 0, 20.333244, 59.297451, 130, 0 },
3276         { 0, 0, 0, 0, 42.304108, 0, 57.563725, 43.700001, 131, 0 } } },
3277     { make_hwstate(1329527921.920301, 0, 2, 2, nullptr), 0,
3278       GESTURES_BUTTON_RIGHT,
3279       { { 0, 0, 0, 0, 55.448730, 0, 20.333294, 59.298725, 130, 0 },
3280         { 0, 0, 0, 0, 41.444939, 0, 57.525326, 43.700001, 131, 0 } } }
3281   };
3282   ImmediateInterpreter ii(nullptr, nullptr);
3283   TestInterpreterWrapper wrapper(&ii, &hwprops);
3284   for (size_t i = 0; i < arraysize(records); i++) {
3285     // Make the hwstate point to the fingers
3286     HardwareState& hs = records[i].hs;
3287     hs.fingers = records[i].fs;
3288     Gesture* gs_out = wrapper.SyncInterpret(hs, nullptr);
3289     if (!gs_out || gs_out->type != kGestureTypeButtonsChange) {
3290       // We got no output buttons gesture. Make sure we expected that
3291       EXPECT_EQ(0, records[i].out_buttons_down);
3292       EXPECT_EQ(0, records[i].out_buttons_up);
3293     } else if (gs_out) {
3294       // We got a buttons gesture
3295       EXPECT_EQ(gs_out->details.buttons.down, records[i].out_buttons_down);
3296       EXPECT_EQ(gs_out->details.buttons.up, records[i].out_buttons_up);
3297     } else {
3298       ADD_FAILURE();  // This should be unreachable
3299     }
3300   }
3301 }
3302 
TEST(ImmediateInterpreterTest,ChangeTimeoutTest)3303 TEST(ImmediateInterpreterTest, ChangeTimeoutTest) {
3304   ImmediateInterpreter ii(nullptr, nullptr);
3305   HardwareProperties hwprops = {
3306     .right = 1000,
3307     .bottom = 1000,
3308     .res_x = 500,
3309     .res_y = 500,
3310     .orientation_minimum = -1,
3311     .orientation_maximum = 2,
3312     .max_finger_cnt = 2,
3313     .max_touch_cnt = 5,
3314     .supports_t5r2 = 0,
3315     .support_semi_mt = 0,
3316     .is_button_pad = 1,
3317     .has_wheel = 0,
3318     .wheel_is_hi_res = 0,
3319     .is_haptic_pad = 0,
3320   };
3321 
3322   FingerState finger_states[] = {
3323     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
3324     {0, 0, 0, 0, 21, 0, 30, 30, 2, 0},
3325     {0, 0, 0, 0, 21, 0, 10, 10, 1, 0},
3326     {0, 0, 0, 0, 21, 0, 10, 20, 1, 0},
3327     {0, 0, 0, 0, 21, 0, 20, 20, 1, 0}
3328   };
3329   HardwareState hardware_states[] = {
3330     // time, buttons down, finger count, finger states pointer
3331     // One finger moves
3332     make_hwstate(0.10, 0, 1, 1, &finger_states[1]),
3333     make_hwstate(0.12, 0, 1, 1, &finger_states[2]),
3334     make_hwstate(0.16, 0, 1, 1, &finger_states[3]),
3335     make_hwstate(0.5, 0, 0, 0, nullptr),
3336     // One finger moves after another finger leaves
3337     make_hwstate(1.09, 0, 2, 2, &finger_states[0]),
3338     make_hwstate(1.10, 0, 1, 1, &finger_states[1]),
3339     make_hwstate(1.12, 0, 1, 1, &finger_states[2]),
3340     make_hwstate(1.36, 0, 1, 1, &finger_states[3]),
3341     make_hwstate(1.5, 0, 0, 0, nullptr),
3342   };
3343 
3344   TestInterpreterWrapper wrapper(&ii, &hwprops);
3345 
3346   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[0], nullptr));
3347 
3348   // One finger moves, change_timeout_ is not applied.
3349   Gesture* gs = wrapper.SyncInterpret(hardware_states[1], nullptr);
3350   ASSERT_NE(nullptr, gs);
3351   EXPECT_EQ(kGestureTypeMove, gs->type);
3352   EXPECT_EQ(0, gs->details.move.dx);
3353   EXPECT_EQ(10, gs->details.move.dy);
3354   EXPECT_EQ(0.10, gs->start_time);
3355   EXPECT_EQ(0.12, gs->end_time);
3356 
3357   // One finger moves, change_timeout_ does not block the gesture.
3358   gs = wrapper.SyncInterpret(hardware_states[2], nullptr);
3359   EXPECT_NE(nullptr, gs);
3360   EXPECT_EQ(kGestureTypeMove, gs->type);
3361   EXPECT_EQ(10, gs->details.move.dx);
3362   EXPECT_EQ(0, gs->details.move.dy);
3363   EXPECT_EQ(0.12, gs->start_time);
3364   EXPECT_EQ(0.16, gs->end_time);
3365 
3366   // No finger.
3367   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[3], nullptr));
3368 
3369   // Start with 2 fingers.
3370   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[4], nullptr));
3371   // One finger leaves, finger_leave_time_ recorded.
3372   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[5], nullptr));
3373   EXPECT_EQ(ii.finger_leave_time_, 1.10);
3374   // One finger moves, change_timeout_ blocks the gesture.
3375   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[6], nullptr));
3376 
3377   // One finger moves, finger_leave_time_ + change_timeout_
3378   // has been passed.
3379   gs = wrapper.SyncInterpret(hardware_states[7], nullptr);
3380   EXPECT_NE(nullptr, gs);
3381   EXPECT_EQ(kGestureTypeMove, gs->type);
3382   EXPECT_EQ(10, gs->details.move.dx);
3383   EXPECT_EQ(0, gs->details.move.dy);
3384   EXPECT_EQ(1.12, gs->start_time);
3385   EXPECT_EQ(1.36, gs->end_time);
3386 
3387   EXPECT_EQ(nullptr, wrapper.SyncInterpret(hardware_states[8], nullptr));
3388 }
3389 
3390 // Tests that fingers that have been present a while, but are stationary,
3391 // can be evaluated multiple times when they start moving.
3392 
3393 enum PinchTestExpectedResult {
3394   kPinch,
3395   kNoPinch,
3396   kAny,
3397   kNull
3398 };
3399 
3400 struct PinchTestInput {
3401   HardwareState hs;
3402   PinchTestExpectedResult expected_result;
3403 };
3404 
TEST(ImmediateInterpreterTest,PinchTests)3405 TEST(ImmediateInterpreterTest, PinchTests) {
3406   ImmediateInterpreter ii(nullptr, nullptr);
3407   ii.pinch_enable_.val_ = 1;
3408   HardwareProperties hwprops = {
3409     .right = 100,
3410     .bottom = 100,
3411     .res_x = 1,
3412     .res_y = 1,
3413     .orientation_minimum = -1,
3414     .orientation_maximum = 2,
3415     .max_finger_cnt = 2,
3416     .max_touch_cnt = 5,
3417     .supports_t5r2 = 0,
3418     .support_semi_mt = 0,
3419     .is_button_pad = 1,
3420     .has_wheel = 0,
3421     .wheel_is_hi_res = 0,
3422     .is_haptic_pad = 0,
3423   };
3424 
3425   FingerState finger_states[] = {
3426     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
3427     // 0: start position
3428     {0, 0, 0, 0, 20, 0, 40, 40, 1, 0},
3429     {0, 0, 0, 0, 20, 0, 90, 90, 2, 0},
3430 
3431     // 2: pinch inwards
3432     {0, 0, 0, 0, 20, 0, 41, 41, 1, 0},
3433     {0, 0, 0, 0, 20, 0, 89, 89, 2, 0},
3434     {0, 0, 0, 0, 20, 0, 42, 42, 1, 0},
3435     {0, 0, 0, 0, 20, 0, 88, 88, 2, 0},
3436     {0, 0, 0, 0, 20, 0, 43, 43, 1, 0},
3437     {0, 0, 0, 0, 20, 0, 87, 87, 2, 0},
3438     {0, 0, 0, 0, 20, 0, 44, 44, 1, 0},
3439     {0, 0, 0, 0, 20, 0, 86, 86, 2, 0},
3440     {0, 0, 0, 0, 20, 0, 45, 45, 1, 0},
3441     {0, 0, 0, 0, 20, 0, 85, 85, 2, 0},
3442 
3443     // 12: pinch outwards
3444     {0, 0, 0, 0, 20, 0, 39, 39, 1, 0},
3445     {0, 0, 0, 0, 20, 0, 91, 91, 2, 0},
3446     {0, 0, 0, 0, 20, 0, 38, 38, 1, 0},
3447     {0, 0, 0, 0, 20, 0, 92, 92, 2, 0},
3448     {0, 0, 0, 0, 20, 0, 37, 37, 1, 0},
3449     {0, 0, 0, 0, 20, 0, 93, 93, 2, 0},
3450     {0, 0, 0, 0, 20, 0, 36, 36, 1, 0},
3451     {0, 0, 0, 0, 20, 0, 94, 94, 2, 0},
3452     {0, 0, 0, 0, 20, 0, 35, 35, 1, 0},
3453     {0, 0, 0, 0, 20, 0, 95, 95, 2, 0},
3454 
3455     // 22: single finger pinch
3456     {0, 0, 0, 0, 20, 0, 39, 39, 1, 0},
3457     {0, 0, 0, 0, 20, 0, 90, 90, 2, 0},
3458     {0, 0, 0, 0, 20, 0, 38, 38, 1, 0},
3459     {0, 0, 0, 0, 20, 0, 90, 90, 2, 0},
3460     {0, 0, 0, 0, 20, 0, 37, 37, 1, 0},
3461     {0, 0, 0, 0, 20, 0, 90, 90, 2, 0},
3462     {0, 0, 0, 0, 20, 0, 36, 36, 1, 0},
3463     {0, 0, 0, 0, 20, 0, 90, 90, 2, 0},
3464     {0, 0, 0, 0, 20, 0, 35, 35, 1, 0},
3465     {0, 0, 0, 0, 20, 0, 90, 90, 2, 0},
3466   };
3467 
3468   PinchTestInput input_states[] = {
3469     // time, buttons, finger count, touch count, finger states pointer
3470     {make_hwstate(0.00, 0, 0, 0, nullptr), kAny},
3471 
3472     // fast pinch outwards
3473     {make_hwstate(0.11, 0, 2, 2, &finger_states[0]), kAny},
3474     {make_hwstate(0.12, 0, 2, 2, &finger_states[4]), kAny},
3475     {make_hwstate(0.13, 0, 2, 2, &finger_states[8]), kAny},
3476     {make_hwstate(0.14, 0, 2, 2, &finger_states[10]), kPinch},
3477     {make_hwstate(0.15, 0, 0, 0, nullptr), kAny},
3478 
3479     // slow pinch
3480     {make_hwstate(1.01, 0, 2, 2, &finger_states[0]), kAny},
3481     {make_hwstate(1.02, 0, 2, 2, &finger_states[0]), kAny},
3482     {make_hwstate(1.03, 0, 2, 2, &finger_states[2]), kAny},
3483     {make_hwstate(1.04, 0, 2, 2, &finger_states[2]), kAny},
3484     {make_hwstate(1.05, 0, 2, 2, &finger_states[4]), kAny},
3485     {make_hwstate(1.06, 0, 2, 2, &finger_states[4]), kAny},
3486     {make_hwstate(1.07, 0, 2, 2, &finger_states[6]), kAny},
3487     {make_hwstate(1.08, 0, 2, 2, &finger_states[6]), kAny},
3488     {make_hwstate(1.09, 0, 2, 2, &finger_states[8]), kAny},
3489     {make_hwstate(1.10, 0, 2, 2, &finger_states[8]), kAny},
3490     {make_hwstate(1.11, 0, 2, 2, &finger_states[10]), kPinch},
3491     {make_hwstate(1.12, 0, 2, 2, &finger_states[10]), kNull},
3492     {make_hwstate(1.13, 0, 0, 0, nullptr), kAny},
3493 
3494     // single finger pinch
3495     {make_hwstate(2.01, 0, 2, 2, &finger_states[22]), kAny},
3496     {make_hwstate(2.02, 0, 2, 2, &finger_states[26]), kAny},
3497     {make_hwstate(2.03, 0, 2, 2, &finger_states[30]), kAny},
3498     {make_hwstate(2.04, 0, 2, 2, &finger_states[30]), kNoPinch},
3499     {make_hwstate(2.05, 0, 0, 0, nullptr), kAny},
3500 
3501 
3502     // first single finger pinch, then second moves too.
3503     {make_hwstate(3.01, 0, 2, 2, &finger_states[22]), kAny},
3504     {make_hwstate(3.02, 0, 2, 2, &finger_states[24]), kAny},
3505     {make_hwstate(3.03, 0, 2, 2, &finger_states[6]), kAny},
3506     {make_hwstate(3.04, 0, 2, 2, &finger_states[8]), kAny},
3507     {make_hwstate(3.05, 0, 2, 2, &finger_states[10]), kPinch},
3508     {make_hwstate(3.06, 0, 0, 0, nullptr), kAny},
3509 
3510     // fast pinch inwards
3511     {make_hwstate(4.01, 0, 2, 2, &finger_states[10]), kAny},
3512     {make_hwstate(4.02, 0, 2, 2, &finger_states[8]), kAny},
3513     {make_hwstate(4.03, 0, 2, 2, &finger_states[4]), kAny},
3514     {make_hwstate(4.04, 0, 2, 2, &finger_states[0]), kPinch},
3515     {make_hwstate(4.05, 0, 0, 0, nullptr), kAny},
3516   };
3517 
3518   TestInterpreterWrapper wrapper(&ii, &hwprops);
3519 
3520   for (size_t idx = 0; idx < arraysize(input_states); ++idx) {
3521     Gesture* gs = wrapper.SyncInterpret(input_states[idx].hs, nullptr);
3522     // assert pinch detected
3523     if (input_states[idx].expected_result == kPinch) {
3524       ASSERT_NE(nullptr, gs);
3525       EXPECT_EQ(kGestureTypePinch, gs->type) << "idx=" << idx;
3526     }
3527     // assert pinch not detected
3528     if (input_states[idx].expected_result == kNoPinch) {
3529       if (gs != nullptr) {
3530         EXPECT_NE(kGestureTypePinch, gs->type);
3531       }
3532     }
3533     // assert if nullptr is not given back
3534     if (input_states[idx].expected_result == kNull) {
3535       ASSERT_EQ(nullptr, gs);
3536     }
3537   }
3538 }
3539 
3540 struct AvoidAccidentalPinchTestInput {
3541   TestCaseStartOrContinueFlag flag;
3542   stime_t now;
3543   float x0, y0, p0, x1, y1, p1;  // (x, y) coordinate + pressure per finger
3544   GestureType expected_gesture;
3545 };
3546 
3547 // These data are from real logs where a move with resting thumb was appempted,
3548 // but pinch code prevented it.
TEST(ImmediateInterpreterTest,AvoidAccidentalPinchTest)3549 TEST(ImmediateInterpreterTest, AvoidAccidentalPinchTest) {
3550   std::unique_ptr<ImmediateInterpreter> ii;
3551   HardwareProperties hwprops = {
3552     .right = 106.666672,
3553     .bottom = 68.000000,
3554     .res_x = 1,
3555     .res_y = 1,
3556     .orientation_minimum = -1,
3557     .orientation_maximum = 2,
3558     .max_finger_cnt = 15,
3559     .max_touch_cnt = 5,
3560     .supports_t5r2 = 0,
3561     .support_semi_mt = 0,
3562     .is_button_pad = true,
3563     .has_wheel = 0,
3564     .wheel_is_hi_res = 0,
3565     .is_haptic_pad = false,
3566   };
3567   TestInterpreterWrapper wrapper(ii.get(), &hwprops);
3568 
3569   const GestureType kMov = kGestureTypeMove;
3570   const GestureType kAny = kGestureTypeNull;
3571 
3572   AvoidAccidentalPinchTestInput inputs[] = {
3573     { kS, 0.97697, 44.08, 64.30, 118.20, 35.91, 27.70, 44.46, kAny },
3574     { kC, 0.98755, 44.08, 64.30, 118.20, 35.91, 27.70, 50.28, kAny },
3575     { kC, 0.99816, 44.08, 64.30, 118.20, 35.91, 27.70, 54.16, kAny },
3576     { kC, 1.00876, 45.33, 65.50,  98.79, 35.91, 27.60, 56.10, kAny },
3577     { kC, 1.01936, 45.33, 65.50,  98.79, 35.91, 27.60, 58.04, kAny },
3578     { kC, 1.03026, 45.33, 65.50, 100.73, 34.50, 26.70, 63.87, kAny },
3579     { kC, 1.04124, 45.33, 65.50, 102.67, 33.00, 26.10, 65.81, kMov },
3580     { kC, 1.05198, 45.33, 65.50, 102.67, 31.25, 25.60, 71.63, kMov },
3581     { kC, 1.06279, 45.33, 65.50, 104.61, 28.75, 25.10, 73.57, kMov },
3582     { kC, 1.07364, 45.33, 65.50, 104.61, 27.00, 24.60, 71.63, kMov },
3583     { kC, 1.08451, 45.33, 65.50, 104.61, 25.41, 24.10, 71.63, kMov },
3584     { kC, 1.09512, 45.33, 65.50, 102.67, 23.58, 23.50, 75.51, kMov },
3585     { kC, 1.10573, 45.33, 65.50, 104.61, 22.25, 23.30, 73.57, kMov },
3586     { kC, 1.11671, 45.33, 65.50, 104.61, 21.16, 23.20, 75.51, kMov },
3587     { kC, 1.12744, 45.33, 65.50, 104.61, 20.25, 23.20, 81.33, kMov },
3588     { kC, 1.13833, 45.33, 65.50, 104.61, 19.41, 23.20, 79.39, kMov },
3589     { kC, 1.14913, 45.33, 65.50, 104.61, 18.33, 23.20, 81.33, kMov },
3590     { kC, 1.15985, 45.41, 65.50, 104.61, 17.50, 23.40, 79.39, kMov },
3591     { kC, 1.17044, 45.58, 65.50, 106.55, 16.75, 23.80, 81.33, kMov },
3592     { kC, 1.18117, 45.58, 65.50, 106.55, 16.33, 24.20, 77.45, kMov },
3593     { kC, 1.19188, 45.58, 65.50, 106.55, 16.00, 24.30, 71.63, kMov },
3594     { kC, 1.20260, 45.58, 65.50, 106.55, 16.00, 24.50, 48.34, kAny },
3595     { kC, 1.21331, 45.58, 65.50, 106.55, 15.91, 24.80,  9.54, kAny },
3596 
3597     { kS, 3.92951, 58.50, 58.40, 118.20, 38.25, 14.40,  3.71, kAny },
3598     { kC, 3.94014, 58.33, 58.40, 118.20, 38.25, 14.40, 38.64, kAny },
3599     { kC, 3.95082, 58.25, 58.40, 118.20, 38.33, 14.40, 50.28, kAny },
3600     { kC, 3.96148, 58.08, 58.40, 118.20, 38.41, 14.40, 52.22, kAny },
3601     { kC, 3.97222, 57.91, 58.40, 118.20, 38.41, 14.50, 56.10, kAny },
3602     { kC, 3.98303, 57.83, 58.40, 118.20, 38.58, 14.60, 59.99, kAny },
3603     { kC, 3.99376, 57.66, 58.40, 118.20, 38.75, 14.80, 63.87, kAny },
3604     { kC, 4.00452, 57.58, 58.40, 118.20, 38.91, 15.00, 65.81, kAny },
3605     { kC, 4.01528, 57.50, 58.40, 118.20, 39.33, 15.30, 67.75, kAny },
3606     { kC, 4.02621, 57.41, 58.40, 118.20, 39.50, 15.70, 69.69, kAny },
3607     { kC, 4.03697, 57.41, 58.40, 118.20, 39.75, 16.10, 73.57, kMov },
3608     { kC, 4.04781, 57.25, 58.40, 118.20, 40.00, 16.60, 71.63, kMov },
3609     { kC, 4.05869, 57.25, 58.40, 118.20, 40.25, 17.00, 71.63, kMov },
3610     { kC, 4.06966, 57.25, 58.40, 118.20, 40.50, 17.30, 69.69, kMov },
3611     { kC, 4.08034, 57.16, 58.40, 118.20, 40.75, 17.70, 71.63, kMov },
3612     { kC, 4.09120, 57.08, 58.40, 118.20, 41.16, 17.90, 73.57, kMov },
3613     { kC, 4.10214, 57.00, 58.40, 118.20, 41.50, 18.30, 73.57, kMov },
3614     { kC, 4.11304, 56.83, 58.29, 118.20, 42.00, 18.60, 71.63, kMov },
3615     { kC, 4.12390, 56.83, 58.29, 118.20, 42.58, 19.00, 71.63, kMov },
3616     { kC, 4.13447, 56.66, 58.29, 118.20, 43.16, 19.60, 67.75, kMov },
3617     { kC, 4.14521, 56.66, 58.29, 118.20, 43.75, 20.20, 67.75, kMov },
3618     { kC, 4.15606, 56.50, 58.20, 118.20, 44.41, 21.10, 69.69, kMov },
3619     { kC, 4.16692, 56.50, 58.20, 118.20, 44.91, 22.10, 67.75, kMov },
3620     { kC, 4.17778, 56.41, 58.20, 118.20, 45.58, 23.00, 65.81, kMov },
3621     { kC, 4.18894, 56.33, 58.10, 118.20, 46.08, 23.60, 65.81, kMov },
3622     { kC, 4.20017, 56.33, 58.10, 118.20, 46.50, 24.10, 65.81, kMov },
3623     { kC, 4.21111, 56.33, 58.10, 118.20, 46.83, 24.50, 63.87, kMov },
3624     { kC, 4.22204, 56.33, 58.10, 118.20, 47.08, 24.80, 61.93, kMov },
3625     { kC, 4.23308, 56.25, 58.10, 118.20, 47.50, 25.20, 59.99, kMov },
3626     { kC, 4.24371, 56.25, 58.10, 118.20, 48.00, 25.80, 58.04, kMov },
3627     { kC, 4.25438, 56.25, 58.10, 118.20, 48.66, 26.50, 58.04, kMov },
3628     { kC, 4.26508, 56.08, 58.00, 118.20, 49.50, 27.50, 54.16, kMov },
3629     { kC, 4.27572, 56.00, 58.00, 118.20, 50.33, 28.60, 56.10, kMov },
3630     { kC, 4.28662, 56.00, 58.00, 118.20, 51.33, 29.50, 58.04, kMov },
3631     { kC, 4.29757, 55.91, 58.00, 118.20, 51.58, 31.90, 56.10, kMov },
3632     { kC, 4.30850, 55.91, 58.00, 118.20, 52.08, 32.00, 54.16, kMov },
3633     { kC, 4.31943, 55.91, 58.00, 118.20, 52.58, 32.40, 54.16, kMov },
3634     { kC, 4.33022, 55.83, 57.90, 118.20, 52.75, 33.10, 52.22, kMov },
3635     { kC, 4.34104, 55.83, 57.90, 118.20, 53.16, 33.60, 52.22, kMov },
3636     { kC, 4.35167, 55.83, 57.90, 118.20, 53.58, 34.20, 50.28, kMov },
3637     { kC, 4.36225, 55.83, 57.90, 118.20, 53.91, 35.00, 48.34, kMov },
3638     { kC, 4.37290, 55.75, 57.90, 118.20, 54.58, 35.50, 50.28, kMov },
3639     { kC, 4.38368, 55.66, 57.90, 118.20, 55.33, 36.10, 48.34, kMov },
3640     { kC, 4.39441, 55.66, 57.90, 118.20, 55.91, 36.70, 48.34, kMov },
3641     { kC, 4.40613, 56.16, 57.90, 118.20, 57.00, 37.20, 50.28, kMov },
3642     { kC, 4.41787, 56.16, 57.90, 118.20, 57.33, 37.70, 50.28, kMov },
3643     { kC, 4.42925, 56.16, 57.90, 118.20, 57.58, 37.90, 48.34, kMov },
3644     { kC, 4.44080, 56.16, 57.90, 118.20, 57.66, 38.00, 50.28, kMov },
3645     { kC, 4.45249, 56.16, 57.90, 118.20, 57.75, 38.10, 50.28, kMov },
3646     { kC, 4.46393, 56.16, 57.90, 118.20, 57.75, 38.10, 50.28, kAny },
3647     { kC, 4.47542, 56.16, 57.90, 118.20, 57.75, 38.15, 50.28, kMov },
3648     { kC, 4.48691, 56.16, 57.90, 118.20, 57.75, 38.20, 50.28, kMov },
3649     { kC, 4.49843, 56.16, 57.90, 118.20, 57.75, 38.20, 50.28, kAny },
3650     { kC, 4.51581, 56.16, 57.90, 118.20, 57.75, 38.25, 51.25, kMov },
3651     { kC, 4.53319, 56.16, 57.90, 118.20, 57.75, 38.29, 52.22, kMov },
3652     { kC, 4.54472, 56.16, 57.90, 118.20, 57.75, 38.70, 50.28, kMov },
3653     { kC, 4.55630, 56.16, 57.90, 118.20, 57.75, 38.70, 50.28, kAny },
3654     { kC, 4.56787, 56.16, 57.90, 118.20, 57.75, 38.70, 52.22, kAny },
3655     { kC, 4.57928, 56.16, 57.90, 118.20, 58.33, 38.50, 50.28, kMov },
3656     { kC, 4.59082, 56.16, 57.90, 118.20, 58.25, 38.60, 50.28, kMov },
3657     { kC, 4.60234, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kMov },
3658     { kC, 4.61389, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3659     { kC, 4.62545, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3660     { kC, 4.64281, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3661     { kC, 4.66018, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3662     { kC, 4.67747, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3663     { kC, 4.69476, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3664     { kC, 4.70628, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3665     { kC, 4.71781, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3666     { kC, 4.72934, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3667     { kC, 4.74087, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3668     { kC, 4.75240, 56.16, 57.90, 118.20, 58.33, 38.60, 52.22, kAny },
3669     { kC, 4.76418, 56.16, 57.90, 118.20, 58.33, 38.60, 50.28, kAny },
3670     { kC, 4.77545, 56.08, 57.90, 118.20, 58.33, 38.60, 50.28, kAny },
3671     { kC, 4.78690, 56.08, 57.90, 118.20, 58.33, 38.60, 48.34, kAny },
3672     { kC, 4.79818, 56.08, 57.90, 118.20, 58.33, 38.60, 27.00, kAny },
3673     { kC, 4.80970, 56.08, 57.90, 118.20, 58.33, 38.60,  9.54, kAny },
3674   };
3675 
3676   for (size_t i = 0; i < arraysize(inputs); i++) {
3677     const AvoidAccidentalPinchTestInput& input = inputs[i];
3678     if (input.flag == kS) {
3679       ii.reset(new ImmediateInterpreter(nullptr, nullptr));
3680       ii->pinch_enable_.val_ = true;
3681       MetricsProperties* mprops = new MetricsProperties(nullptr);
3682       mprops->two_finger_close_vertical_distance_thresh.val_ = 35.0;
3683       wrapper.Reset(ii.get(), mprops);
3684       EXPECT_EQ(ImmediateInterpreter::TapToClickState::kTtcIdle,
3685                 ii->tap_to_click_state());
3686     }
3687     // Prep inputs
3688     FingerState fs[] = {
3689       { 0, 0, 0, 0, input.p0, 0, input.x0, input.y0, 1, 0 },
3690       { 0, 0, 0, 0, input.p1, 0, input.x1, input.y1, 2, 0 },
3691     };
3692     HardwareState hs = make_hwstate(input.now, 0, 2, 2, fs);
3693     stime_t timeout = NO_DEADLINE;
3694     Gesture* gs = wrapper.SyncInterpret(hs, &timeout);
3695     if (input.expected_gesture != kAny) {
3696       if (gs)
3697         EXPECT_EQ(input.expected_gesture, gs->type);
3698     }
3699   }
3700 }
3701 
TEST(ImmediateInterpreterTest,SemiMtActiveAreaTest)3702 TEST(ImmediateInterpreterTest, SemiMtActiveAreaTest) {
3703   ImmediateInterpreter ii(nullptr, nullptr);
3704 
3705   HardwareProperties old_hwprops = {
3706     .right = 90.404251,
3707     .bottom = 48.953846,
3708     .res_x = 1,
3709     .res_y = 1,
3710     .orientation_minimum = -1,
3711     .orientation_maximum = 2,
3712     .max_finger_cnt = 2,
3713     .max_touch_cnt = 3,
3714     .supports_t5r2 = 0,
3715     .support_semi_mt = 1,
3716     .is_button_pad = true,
3717     .has_wheel = 0,
3718     .wheel_is_hi_res = 0,
3719     .is_haptic_pad = false,
3720   };
3721 
3722   const unsigned kNonPalmFlags = GESTURES_FINGER_WARP_X |
3723       GESTURES_FINGER_WARP_Y;
3724   const unsigned kPalmFlags = kNonPalmFlags | GESTURES_FINGER_PALM;
3725 
3726   FingerState old_finger_states[] = {
3727     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID, flags
3728     { 0, 0, 0, 0, 14, 0, 50, 8, 11, kPalmFlags },
3729     { 0, 0, 0, 0, 33, 0, 50, 8, 11, kPalmFlags },
3730     { 0, 0, 0, 0, 37, 0, 50, 8, 11, kPalmFlags },
3731     { 0, 0, 0, 0, 39, 0, 50, 8, 11, kPalmFlags },
3732   };
3733 
3734   HardwareState old_hardware_states[] = {
3735     // time, buttons down, finger count, touch count, finger states pointer
3736     make_hwstate(0.05, 0, 1, 1, &old_finger_states[0]),
3737     make_hwstate(0.10, 0, 1, 1, &old_finger_states[1]),
3738     make_hwstate(0.15, 0, 1, 1, &old_finger_states[2]),
3739     make_hwstate(0.20, 0, 1, 1, &old_finger_states[3]),
3740   };
3741 
3742   TestInterpreterWrapper wrapper(&ii, &old_hwprops);
3743   ii.tap_enable_.val_ = 1;
3744 
3745   // The finger will not change the tap_to_click_state_ at all.
3746   for (size_t idx = 0; idx < arraysize(old_hardware_states); ++idx) {
3747     wrapper.SyncInterpret(old_hardware_states[idx], nullptr);
3748     EXPECT_EQ(kIdl, ii.tap_to_click_state_);
3749   }
3750 
3751   HardwareProperties new_hwprops = {
3752     .right = 96.085106,
3753     .bottom = 57.492310,
3754     .res_x = 1,
3755     .res_y = 1,
3756     .orientation_minimum = -1,
3757     .orientation_maximum = 2,
3758     .max_finger_cnt = 2,
3759     .max_touch_cnt = 3,
3760     .supports_t5r2 = 0,
3761     .support_semi_mt = 1,
3762     .is_button_pad = true,
3763     .has_wheel = 0,
3764     .wheel_is_hi_res = 0,
3765     .is_haptic_pad = false,
3766   };
3767 
3768   FingerState new_finger_states[] = {
3769     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID, flags
3770     { 0, 0, 0, 0, 14, 0, 55, 12, 7, kNonPalmFlags },
3771     { 0, 0, 0, 0, 33, 0, 55, 12, 7, kNonPalmFlags },
3772     { 0, 0, 0, 0, 37, 0, 55, 12, 7, kNonPalmFlags },
3773     { 0, 0, 0, 0, 39, 0, 55, 12, 7, kNonPalmFlags },
3774   };
3775 
3776   HardwareState new_hardware_states[] = {
3777     // time, buttons down, finger count, touch count, finger states pointer
3778     make_hwstate(0.05, 0, 1, 1, &new_finger_states[0]),
3779     make_hwstate(0.10, 0, 1, 1, &new_finger_states[1]),
3780     make_hwstate(0.15, 0, 1, 1, &new_finger_states[2]),
3781     make_hwstate(0.20, 0, 1, 1, &new_finger_states[3]),
3782   };
3783 
3784   wrapper.Reset(&ii, &new_hwprops);
3785   ii.tap_enable_.val_ = true;
3786 
3787   // With new active area, the finger changes the tap_to_click_state_ to
3788   // FirstTapBegan.
3789   for (size_t idx = 0; idx < arraysize(new_hardware_states); ++idx) {
3790     wrapper.SyncInterpret(new_hardware_states[idx], nullptr);
3791     EXPECT_EQ(ii.kTtcFirstTapBegan, ii.tap_to_click_state_);
3792   }
3793 }
3794 
TEST(ImmediateInterpreterTest,SemiMtNoPinchTest)3795 TEST(ImmediateInterpreterTest, SemiMtNoPinchTest) {
3796   ImmediateInterpreter ii(nullptr, nullptr);
3797   ii.pinch_enable_.val_ = 1;
3798 
3799   HardwareProperties hwprops = {
3800     .right = 90.404251,
3801     .bottom = 48.953846,
3802     .res_x = 1,
3803     .res_y = 1,
3804     .orientation_minimum = -1,
3805     .orientation_maximum = 2,
3806     .max_finger_cnt = 2,
3807     .max_touch_cnt = 3,
3808     .supports_t5r2 = 0,
3809     .support_semi_mt = 0,
3810     .is_button_pad = true,
3811     .has_wheel = 0,
3812     .wheel_is_hi_res = 0,
3813     .is_haptic_pad = false,
3814   };
3815 
3816   FingerState finger_state[] = {
3817     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID, flags
3818     {0, 0, 0, 0, 25, 0, 30, 53, 1, 0},  // index 0
3819     {0, 0, 0, 0, 46, 0, 30, 53, 1, 0},  // index 1
3820     {0, 0, 0, 0, 69, 0, 30, 53, 1, 0},  // index 2
3821 
3822     {0, 0, 0, 0, 67, 0, 30, 53, 1, 0},  // index 3
3823     {0, 0, 0, 0, 67, 0, 68, 27, 2, 0},
3824 
3825     {0, 0, 0, 0, 91, 0, 43, 52, 1, 0},  // index 5
3826     {0, 0, 0, 0, 91, 0, 44, 23, 2, 0},
3827 
3828     {0, 0, 0, 0, 91, 0, 43, 52, 1, 0},  // index 7
3829     {0, 0, 0, 0, 91, 0, 43, 23, 2, 0},
3830   };
3831 
3832 
3833   HardwareState hardware_states[] = {
3834     // time, buttons down, finger count, touch count, finger states pointer
3835     make_hwstate(2106.273252, 0, 1, 1, &finger_state[0]),
3836     make_hwstate(2106.285466, 0, 1, 1, &finger_state[1]),
3837     make_hwstate(2106.298021, 0, 1, 1, &finger_state[2]),
3838     make_hwstate(2106.325599, 0, 2, 2, &finger_state[3]),
3839     make_hwstate(2106.648152, 0, 2, 2, &finger_state[5]),
3840     make_hwstate(2106.660447, 0, 2, 2, &finger_state[7]),
3841     // pinch if not semi_mt device
3842   };
3843 
3844   TestInterpreterWrapper wrapper(&ii, &hwprops);
3845 
3846   Gesture *gesture;
3847   for (size_t idx = 0; idx < arraysize(hardware_states); ++idx) {
3848     gesture = wrapper.SyncInterpret(hardware_states[idx], nullptr);
3849     // reset finger flags
3850     for (size_t fidx = 0; fidx < hardware_states[idx].finger_cnt; ++fidx)
3851       hardware_states[idx].fingers[fidx].flags = 0;
3852   }
3853   if (gesture)
3854     EXPECT_EQ(gesture->type, kGestureTypePinch);
3855 
3856   // For a semi_mt device, replay the same inputs should not generate
3857   // a pinch gesture.
3858   hwprops.support_semi_mt = 1;
3859   wrapper.Reset(&ii, &hwprops);
3860   for (size_t idx = 0; idx < arraysize(hardware_states); ++idx) {
3861     gesture = wrapper.SyncInterpret(hardware_states[idx], nullptr);
3862     // reset finger flags
3863     for (size_t fidx = 0; fidx < hardware_states[idx].finger_cnt; ++fidx)
3864       hardware_states[idx].fingers[fidx].flags = 0;
3865   }
3866   if (gesture)
3867     EXPECT_NE(gesture->type, kGestureTypePinch);
3868 }
3869 
TEST(ImmediateInterpreterTest,WarpedFingersTappingTest)3870 TEST(ImmediateInterpreterTest, WarpedFingersTappingTest) {
3871   ImmediateInterpreter ii(nullptr, nullptr);
3872 
3873   HardwareProperties hwprops = {
3874     .right = 90.404251,
3875     .bottom = 48.953846,
3876     .res_x = 1,
3877     .res_y = 1,
3878     .orientation_minimum = -1,
3879     .orientation_maximum = 2,
3880     .max_finger_cnt = 2,
3881     .max_touch_cnt = 3,
3882     .supports_t5r2 = 0,
3883     .support_semi_mt = 1,
3884     .is_button_pad = true,
3885     .has_wheel = 0,
3886     .wheel_is_hi_res = 0,
3887     .is_haptic_pad = false,
3888   };
3889 
3890   unsigned flags = GESTURES_FINGER_WARP_X_NON_MOVE |
3891       GESTURES_FINGER_WARP_Y_NON_MOVE |
3892       GESTURES_FINGER_WARP_X_TAP_MOVE |
3893       GESTURES_FINGER_WARP_Y_TAP_MOVE;
3894 
3895   FingerState finger_state[] = {
3896     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID, flags
3897     { 0, 0, 0, 0, 42.139996, 0, 46.106384, 39.800003, 0, flags },  // index 0
3898     { 0, 0, 0, 0, 42.139996, 0, 69.106384, 28.461538, 1, flags },
3899 
3900     // The finger 0 moves more than default threshold 2.0 in Y, but it should
3901     // still generate final right-click gesture as the WARP flag is set.
3902     { 0, 0, 0, 0, 43.350002, 0, 45.425529, 36.353844, 0, flags },  // index 2
3903     { 0, 0, 0, 0, 43.350002, 0, 69.063828, 28.507692, 1, flags },
3904 
3905     { 0, 0, 0, 0, 43.350002, 0, 69.085106, 28.307692, 1, flags },  // index 4
3906   };
3907 
3908   HardwareState hardware_states[] = {
3909     // time, buttons down, finger count, touch count, finger states pointer
3910     make_hwstate(3897.124791, 0, 2, 2, &finger_state[0]),
3911     make_hwstate(3897.136733, 0, 2, 2, &finger_state[2]),
3912     make_hwstate(3897.148675, 0, 1, 1, &finger_state[4]),
3913     make_hwstate(3897.160675, 0, 0, 0, nullptr),
3914   };
3915 
3916   ii.tap_enable_.val_ = 1;
3917   TestInterpreterWrapper wrapper(&ii, &hwprops);
3918 
3919   Gesture *gesture;
3920   for (size_t idx = 0; idx < arraysize(hardware_states); ++idx)
3921     gesture = wrapper.SyncInterpret(hardware_states[idx], nullptr);
3922 
3923   ASSERT_NE(gesture, nullptr);
3924   EXPECT_EQ(gesture->type, kGestureTypeButtonsChange);
3925 }
3926 
3927 // Test that fling_buffer_depth controls the number of scroll samples to use
3928 // to compute fling.
TEST(ImmediateInterpreterTest,FlingDepthTest)3929 TEST(ImmediateInterpreterTest, FlingDepthTest) {
3930   ImmediateInterpreter ii(nullptr, nullptr);
3931   HardwareProperties hwprops = {
3932     .right = 100,
3933     .bottom = 100,
3934     .res_x = 1,
3935     .res_y = 1,
3936     .orientation_minimum = -1,
3937     .orientation_maximum = 2,
3938     .max_finger_cnt = 2,
3939     .max_touch_cnt = 5,
3940     .supports_t5r2 = 0,
3941     .support_semi_mt = 1,
3942     .is_button_pad = 1,
3943     .has_wheel = 0,
3944     .wheel_is_hi_res = 0,
3945     .is_haptic_pad = 0,
3946   };
3947 
3948   FingerState finger_states[] = {
3949     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID
3950     // Consistent movement for 6 frames
3951     {0, 0, 0, 0, 20, 0, 40, 20, 1, 0}, // 0
3952     {0, 0, 0, 0, 20, 0, 60, 20, 2, 0},
3953 
3954     {0, 0, 0, 0, 20, 0, 40, 25, 1, 0}, // 2
3955     {0, 0, 0, 0, 20, 0, 60, 25, 2, 0},
3956 
3957     {0, 0, 0, 0, 20, 0, 40, 30, 1, 0}, // 4
3958     {0, 0, 0, 0, 20, 0, 60, 30, 2, 0},
3959 
3960     {0, 0, 0, 0, 20, 0, 40, 35, 1, 0}, // 6
3961     {0, 0, 0, 0, 20, 0, 60, 35, 2, 0},
3962 
3963     {0, 0, 0, 0, 20, 0, 40, 40, 1, 0}, // 8
3964     {0, 0, 0, 0, 20, 0, 60, 40, 2, 0},
3965 
3966     {0, 0, 0, 0, 20, 0, 40, 45, 1, 0}, // 10
3967     {0, 0, 0, 0, 20, 0, 60, 45, 2, 0},
3968 
3969     {0, 0, 0, 0, 20, 0, 40, 50, 1, 0}, // 12
3970     {0, 0, 0, 0, 20, 0, 60, 50, 2, 0},
3971 
3972     {0, 0, 0, 0, 20, 0, 40, 55, 1, 0}, // 14
3973     {0, 0, 0, 0, 20, 0, 60, 55, 2, 0},
3974   };
3975   HardwareState hardware_states[] = {
3976     // time, buttons, finger count, touch count, finger states pointer
3977     make_hwstate(1.00, 0, 2, 2, &finger_states[0]),
3978     make_hwstate(1.01, 0, 2, 2, &finger_states[2]),
3979     make_hwstate(1.02, 0, 2, 2, &finger_states[4]),
3980     make_hwstate(1.03, 0, 2, 2, &finger_states[6]),
3981     make_hwstate(1.04, 0, 2, 2, &finger_states[8]),
3982     make_hwstate(1.05, 0, 2, 2, &finger_states[10]),
3983     make_hwstate(1.06, 0, 2, 2, &finger_states[12]),
3984     make_hwstate(1.07, 0, 2, 2, &finger_states[14]),
3985   };
3986 
3987   TestInterpreterWrapper wrapper(&ii, &hwprops);
3988 
3989   ii.scroll_manager_.fling_buffer_depth_.val_ = 6;
3990   size_t fling_buffer_depth =
3991     (size_t)ii.scroll_manager_.fling_buffer_depth_.val_;
3992 
3993   // The unittest is only meaningful if there are enough hwstates
3994   ASSERT_GT(arraysize(hardware_states) - 1, fling_buffer_depth)
3995       << "Hardware state list must be > fling buffer depth + 1";
3996 
3997   // Fill scroll buffer with a set of scrolls
3998   ii.scroll_buffer_.Clear();
3999   const HardwareState* prev_hs = nullptr;
4000   for (size_t idx = 0; idx < arraysize(hardware_states); ++idx) {
4001     const HardwareState* hs = &hardware_states[idx];
4002     if (prev_hs != nullptr) {
4003       // Cheating here, only using first finger to compute scroll
4004       const FingerState* fs = &hs->fingers[0];
4005       const FingerState* prev_fs = prev_hs->GetFingerState(fs->tracking_id);
4006       EXPECT_NE(nullptr, prev_fs);
4007       float dx = fs->position_x - prev_fs->position_x;
4008       float dy = fs->position_y - prev_fs->position_y;
4009       float dt = hs->timestamp - prev_hs->timestamp;
4010       ii.scroll_buffer_.Insert(dx, dy, hs->timestamp, prev_hs->timestamp);
4011       // Enforce assumption that all scrolls are positive in Y only
4012       EXPECT_DOUBLE_EQ(dx, 0);
4013       EXPECT_GT(dy, 0);
4014       EXPECT_GT(dt, 0);
4015       size_t expected_fling_events = std::min(idx, fling_buffer_depth);
4016       EXPECT_EQ(ii.scroll_manager_.ScrollEventsForFlingCount(ii.scroll_buffer_),
4017                 expected_fling_events);
4018     }
4019     prev_hs = hs;
4020   }
4021 }
4022 
TEST(ImmediateInterpreterTest,ScrollResetTapTest)4023 TEST(ImmediateInterpreterTest, ScrollResetTapTest) {
4024   ImmediateInterpreter ii(nullptr, nullptr);
4025 
4026   HardwareProperties hwprops = {
4027     .right = 96.085106,
4028     .bottom = 57.492310,
4029     .res_x = 1,
4030     .res_y = 1,
4031     .orientation_minimum = -1,
4032     .orientation_maximum = 2,
4033     .max_finger_cnt = 2,
4034     .max_touch_cnt = 3,
4035     .supports_t5r2 = 0,
4036     .support_semi_mt = 1,
4037     .is_button_pad = 1,
4038     .has_wheel = 0,
4039     .wheel_is_hi_res = 0,
4040     .is_haptic_pad = 0,
4041   };
4042 
4043   FingerState finger_state[] = {
4044     // TM, Tm, WM, Wm, Press, Orientation, X, Y, TrID, flags
4045     { 0, 0, 0, 0, 71.180000, 0, 58.446808, 24.000002, 0, 3 },  // index 0
4046     { 0, 0, 0, 0, 71.180000, 0, 75.042549, 23.676924, 1, 3 },
4047 
4048     { 0, 0, 0, 0, 82.070000, 0, 55.276596, 23.492308, 0, 3 },  // index 2
4049     { 0, 0, 0, 0, 82.070000, 0, 70.361702, 23.015387, 1, 3 },
4050 
4051     { 0, 0, 0, 0, 76.625000, 0, 58.542553, 23.030769, 0, 3 },  // index 4
4052     { 0, 0, 0, 0, 76.625000, 0, 59.127659, 22.500002, 1, 1 },
4053 
4054     // prev_result will be scroll, we expect the tap state will be idle
4055     // after the sample is processed.
4056     { 0, 0, 0, 0, 71.180000, 0, 61.808510, 22.569231, 0, 3 },  // index 6
4057     { 0, 0, 0, 0, 71.180000, 0, 47.893616, 21.984617, 1, 1 },
4058 
4059     { 0, 0, 0, 0, 16.730000, 0, 57.617020, 20.830770, 0, 3 },  // index 8
4060   };
4061 
4062   HardwareState hardware_states[] = {
4063     // time, buttons down, finger count, touch count, finger states pointer
4064     make_hwstate(1296.498245, 0, 2, 2, &finger_state[0]),
4065     make_hwstate(1296.510735, 0, 2, 2, &finger_state[2]),
4066     make_hwstate(1296.523224, 0, 2, 2, &finger_state[4]),
4067     make_hwstate(1296.535753, 0, 2, 2, &finger_state[6]),
4068     make_hwstate(1296.548282, 0, 1, 1, &finger_state[8]),
4069   };
4070 
4071   // SemiMt-specific properties
4072   ii.tapping_finger_min_separation_.val_ = 0.0;
4073 
4074   ii.tap_enable_.val_ = 1;
4075   TestInterpreterWrapper wrapper(&ii, &hwprops);
4076 
4077   for (size_t idx = 0; idx < arraysize(hardware_states); ++idx) {
4078     Gesture* gs = wrapper.SyncInterpret(hardware_states[idx], nullptr);
4079     if (gs != nullptr) {
4080       if (idx == 2)
4081         EXPECT_EQ(kGestureTypeScroll, gs->type);
4082       else
4083         EXPECT_NE(kGestureTypeButtonsChange, gs->type);
4084     }
4085     if (idx >= 3)
4086       EXPECT_EQ(kIdl, ii.tap_to_click_state_);
4087   }
4088 }
4089 
TEST(ImmediateInterpreterTest,ZeroClickInitializationTest)4090 TEST(ImmediateInterpreterTest, ZeroClickInitializationTest) {
4091   ImmediateInterpreter ii(nullptr, nullptr);
4092 
4093   HardwareProperties hwprops = {
4094     .right = 1000,
4095     .bottom = 1000,
4096     .res_x = 500,
4097     .res_y = 500,
4098     .orientation_minimum = -1,
4099     .orientation_maximum = 2,
4100     .max_finger_cnt = 2,
4101     .max_touch_cnt = 5,
4102     .supports_t5r2 = 0,
4103     .support_semi_mt = 0,
4104     .is_button_pad = 1,
4105     .has_wheel = 0,
4106     .wheel_is_hi_res = 0,
4107     .is_haptic_pad = 0,
4108   };
4109   TestInterpreterWrapper wrapper(&ii, &hwprops);
4110 
4111   // Test touchpad with intergrated button switch.
4112   EXPECT_EQ(0, ii.zero_finger_click_enable_.val_);
4113   // Test touchpad with separate buttons.
4114   hwprops.is_button_pad = 0;
4115   wrapper.Reset(&ii, &hwprops);
4116   EXPECT_EQ(1, ii.zero_finger_click_enable_.val_);
4117 }
4118 
TEST(ImmediateInterpreterTest,PointTest)4119 TEST(ImmediateInterpreterTest, PointTest) {
4120   Point point;
4121   Point point_eq;
4122   Point point_ne0(42.0, 0.0);
4123   Point point_ne1(0.0, 42.0);
4124   EXPECT_TRUE(point == point_eq);
4125   EXPECT_FALSE(point == point_ne0);
4126   EXPECT_FALSE(point == point_ne1);
4127   EXPECT_FALSE(point != point_eq);
4128   EXPECT_TRUE(point != point_ne0);
4129   EXPECT_TRUE(point != point_ne1);
4130 }
4131 
4132 }  // namespace gestures
4133