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