• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 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 <deque>
6 #include <math.h>
7 #include <set>
8 #include <stdio.h>
9 #include <utility>
10 #include <vector>
11 
12 #include <gtest/gtest.h>
13 
14 #include "include/gestures.h"
15 #include "include/lookahead_filter_interpreter.h"
16 #include "include/string_util.h"
17 #include "include/unittest_util.h"
18 #include "include/util.h"
19 
20 using std::deque;
21 using std::pair;
22 
23 namespace gestures {
24 
25 class LookaheadFilterInterpreterTest : public ::testing::Test {};
26 class LookaheadFilterInterpreterParmTest :
27           public LookaheadFilterInterpreterTest,
28           public testing::WithParamInterface<int> {};
29 
30 class LookaheadFilterInterpreterTestInterpreter : public Interpreter {
31  public:
LookaheadFilterInterpreterTestInterpreter()32   LookaheadFilterInterpreterTestInterpreter()
33       : Interpreter(nullptr, nullptr, false),
34         timer_return_(NO_DEADLINE),
35         clear_incoming_hwstates_(false), expected_id_(-1),
36         expected_flags_(0), expected_flags_at_(-1),
37         expected_flags_at_occurred_(false) {}
38 
SyncInterpret(HardwareState & hwstate,stime_t * timeout)39   virtual void SyncInterpret(HardwareState& hwstate, stime_t* timeout) {
40     for (size_t i = 0; i < hwstate.finger_cnt; i++)
41       all_ids_.insert(hwstate.fingers[i].tracking_id);
42     if (expected_id_ >= 0) {
43       EXPECT_EQ(1, hwstate.finger_cnt);
44       EXPECT_EQ(expected_id_, hwstate.fingers[0].tracking_id);
45     }
46     if (!expected_ids_.empty()) {
47       EXPECT_EQ(expected_ids_.size(), hwstate.finger_cnt);
48       for (std::set<short>::iterator it = expected_ids_.begin(),
49                e = expected_ids_.end(); it != e; ++it) {
50         EXPECT_TRUE(hwstate.GetFingerState(*it)) << "Can't find ID " << *it
51                                                   << " at "
52                                                   << hwstate.timestamp;
53       }
54     }
55     if (expected_flags_at_ >= 0 &&
56         DoubleEq(expected_flags_at_, hwstate.timestamp) &&
57         hwstate.finger_cnt > 0) {
58       EXPECT_EQ(expected_flags_, hwstate.fingers[0].flags);
59       expected_flags_at_occurred_ = true;
60     }
61     if (clear_incoming_hwstates_)
62       hwstate.finger_cnt = 0;
63     if (timer_return_ >= 0.0) {
64       *timeout = timer_return_;
65       timer_return_ = NO_DEADLINE;
66     }
67     if (return_values_.empty())
68       return;
69     return_value_ = return_values_.front();
70     return_values_.pop_front();
71     ProduceGesture(return_value_);
72   }
73 
HandleTimer(stime_t now,stime_t * timeout)74   virtual void HandleTimer(stime_t now, stime_t* timeout) {
75     EXPECT_TRUE(false);
76   }
77 
78   Gesture return_value_;
79   deque<Gesture> return_values_;
80   stime_t timer_return_;
81   bool clear_incoming_hwstates_;
82   // if expected_id_ >= 0, we expect that there is one finger with
83   // the expected id.
84   short expected_id_;
85   // if expected_ids_ is populated, we expect fingers w/ exactly those IDs
86   std::set<short> expected_ids_;
87   // If we get a hardware state at time expected_flags_at_, it should have
88   // the following flags set.
89   unsigned expected_flags_;
90   stime_t expected_flags_at_;
91   bool expected_flags_at_occurred_;
92   std::set<short> all_ids_;
93 };
94 
TEST_P(LookaheadFilterInterpreterParmTest,SimpleTest)95 TEST_P(LookaheadFilterInterpreterParmTest, SimpleTest) {
96   LookaheadFilterInterpreterTestInterpreter* base_interpreter = nullptr;
97   std::unique_ptr<LookaheadFilterInterpreter> interpreter;
98 
99   HardwareProperties initial_hwprops = {
100     .right = 100, .bottom = 100,
101     .res_x = 10,
102     .res_y = 10,
103     .screen_x_dpi = 0,
104     .screen_y_dpi = 0,
105     .orientation_minimum = -1,
106     .orientation_maximum = 2,
107     .max_finger_cnt = 2, .max_touch_cnt = 5,
108     .supports_t5r2 = 1, .support_semi_mt = 0, .is_button_pad = 0,
109     .has_wheel = 0, .wheel_is_hi_res = 0,
110     .is_haptic_pad = 0,
111   };
112   TestInterpreterWrapper wrapper(interpreter.get(), &initial_hwprops);
113 
114   FingerState fs[] = {
115     // TM, Tm, WM, Wm, pr, orient, x, y, id
116     { 0, 0, 0, 0, 1, 0, 10, 1, 1, 0 },
117     { 0, 0, 0, 0, 1, 0, 10, 2, 1, 0 },
118     { 0, 0, 0, 0, 1, 0, 10, 3, 1, 0 },
119 
120     { 0, 0, 0, 0, 1, 0, 10, 1, 2, 0 },
121     { 0, 0, 0, 0, 1, 0, 10, 2, 2, 0 },
122 
123     { 0, 0, 0, 0, 1, 0, 10, 1, 3, 0 },
124     { 0, 0, 0, 0, 1, 0, 10, 2, 3, 0 },
125   };
126   HardwareState hs[] = {
127     // Expect movement to take
128     make_hwstate(1.01, 0, 1, 1, &fs[0]),
129     make_hwstate(1.02, 0, 1, 1, &fs[1]),
130     make_hwstate(1.03, 0, 1, 1, &fs[2]),
131 
132     // Expect no movement
133     make_hwstate(2.010, 0, 1, 1, &fs[3]),
134     make_hwstate(2.030, 0, 1, 1, &fs[4]),
135     make_hwstate(2.031, 0, 0, 0, nullptr),
136 
137     // Expect movement b/c it's moving really fast
138     make_hwstate(3.010, 0, 1, 1, &fs[5]),
139     make_hwstate(3.011, 0, 1, 1, &fs[6]),
140     make_hwstate(3.030, 0, 0, 0, nullptr),
141   };
142 
143   stime_t expected_timeout = 0.0;
144   Gesture expected_movement;
145   int suppress = GetParam();
146 
147   for (size_t i = 3; i < arraysize(hs); ++i) {
148     if (i % 3 == 0) {
149       base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
150 
151       for (size_t j = 0; j < 2; ++j) {
152         if (hs[i + j + 1].finger_cnt == 0)
153           break;
154         expected_movement = Gesture(kGestureMove,
155                                     hs[i + j].timestamp,  // start time
156                                     hs[i + j + 1].timestamp,  // end time
157                                     hs[i + j + 1].fingers[0].position_x -
158                                     hs[i + j].fingers[0].position_x,  // dx
159                                     hs[i + j + 1].fingers[0].position_y -
160                                     hs[i + j].fingers[0].position_y);  // dy
161         base_interpreter->return_values_.push_back(expected_movement);
162       }
163 
164       interpreter.reset(new LookaheadFilterInterpreter(
165           nullptr, base_interpreter, nullptr));
166       wrapper.Reset(interpreter.get());
167       interpreter->min_delay_.val_ = 0.05;
168       expected_timeout = interpreter->min_delay_.val_;
169       interpreter->suppress_immediate_tapdown_.val_ = suppress;
170     }
171     stime_t timeout = NO_DEADLINE;
172     Gesture* out = wrapper.SyncInterpret(hs[i], &timeout);
173     if (out) {
174       EXPECT_EQ(kGestureTypeFling, out->type);
175       EXPECT_EQ(GESTURES_FLING_TAP_DOWN, out->details.fling.fling_state);
176     }
177     EXPECT_LT(fabs(expected_timeout - timeout), 0.0000001);
178     if ((i % 3) != 2) {
179       expected_timeout -= hs[i + 1].timestamp - hs[i].timestamp;
180     } else {
181       stime_t newtimeout = NO_DEADLINE;
182       out = wrapper.HandleTimer(hs[i].timestamp + timeout, &newtimeout);
183       if (newtimeout < 0.0)
184         EXPECT_DOUBLE_EQ(NO_DEADLINE, newtimeout);
185       if (i == 5) {
186         EXPECT_EQ(nullptr, out);
187       } else {
188         // Expect movement
189         ASSERT_TRUE(out);
190         EXPECT_EQ(kGestureTypeMove, out->type);
191         EXPECT_EQ(expected_movement.start_time, out->start_time);
192         EXPECT_EQ(expected_movement.end_time, out->end_time);
193         EXPECT_EQ(expected_movement.details.move.dx, out->details.move.dx);
194         EXPECT_EQ(expected_movement.details.move.dy, out->details.move.dy);
195       }
196       // Run through rest of interpreter timeouts, makeing sure we get
197       // reasonable timeout values
198       int cnt = 0;
199       stime_t now = hs[i].timestamp + timeout;
200       while (newtimeout >= 0.0) {
201         if (cnt++ == 10)
202           break;
203         timeout = newtimeout;
204         newtimeout = NO_DEADLINE;
205         now += timeout;
206         out = wrapper.HandleTimer(now, &newtimeout);
207         if (newtimeout >= 0.0)
208           EXPECT_LT(newtimeout, 1.0);
209         else
210           EXPECT_DOUBLE_EQ(NO_DEADLINE, newtimeout);
211       }
212     }
213   }
214 }
215 INSTANTIATE_TEST_SUITE_P(LookaheadFilterInterpreter,
216                          LookaheadFilterInterpreterParmTest,
217                          testing::Values(0, 1));
218 
219 class LookaheadFilterInterpreterVariableDelayTestInterpreter
220     : public Interpreter {
221  public:
LookaheadFilterInterpreterVariableDelayTestInterpreter()222   LookaheadFilterInterpreterVariableDelayTestInterpreter()
223       : Interpreter(nullptr, nullptr, false), interpret_call_count_ (0) {}
224 
SyncInterpret(HardwareState & hwstate,stime_t * timeout)225   virtual void SyncInterpret(HardwareState& hwstate, stime_t* timeout) {
226     interpret_call_count_++;
227     EXPECT_EQ(1, hwstate.finger_cnt);
228     finger_ids_.insert(hwstate.fingers[0].tracking_id);
229   }
230 
HandleTimer(stime_t now,stime_t * timeout)231   virtual void HandleTimer(stime_t now, stime_t* timeout) {
232     EXPECT_TRUE(false);
233   }
234 
235   std::set<short> finger_ids_;
236   size_t interpret_call_count_;
237 };
238 
239 // Tests that with a zero delay, we can still avoid unnecessary splitting
240 // by using variable delay.
TEST(LookaheadFilterInterpreterTest,VariableDelayTest)241 TEST(LookaheadFilterInterpreterTest, VariableDelayTest) {
242   LookaheadFilterInterpreterVariableDelayTestInterpreter* base_interpreter =
243       new LookaheadFilterInterpreterVariableDelayTestInterpreter;
244   LookaheadFilterInterpreter interpreter(nullptr, base_interpreter, nullptr);
245 
246   HardwareProperties initial_hwprops = {
247     .right = 100, .bottom = 100,
248     .res_x = 1,
249     .res_y = 1,
250     .screen_x_dpi = 0,
251     .screen_y_dpi = 0,
252     .orientation_minimum = -1,
253     .orientation_maximum = 2,
254     .max_finger_cnt = 5, .max_touch_cnt = 5,
255     .supports_t5r2 = 0, .support_semi_mt = 0, .is_button_pad = 0,
256     .has_wheel = 0, .wheel_is_hi_res = 0,
257     .is_haptic_pad = 0,
258   };
259   TestInterpreterWrapper wrapper(&interpreter, &initial_hwprops);
260 
261   FingerState fs[] = {
262     // TM, Tm, WM, Wm, pr, orient, x, y, id
263     { 0, 0, 0, 0, 1, 0, 10, 10, 10, 1 },
264     { 0, 0, 0, 0, 1, 0, 10, 30, 10, 1 },
265     { 0, 0, 0, 0, 1, 0, 10, 50, 10, 1 },
266   };
267   HardwareState hs[] = {
268     // Expect movement to take
269     make_hwstate(1.01, 0, 1, 1, &fs[0]),
270     make_hwstate(1.02, 0, 1, 1, &fs[1]),
271     make_hwstate(1.03, 0, 1, 1, &fs[2]),
272   };
273 
274   interpreter.min_delay_.val_ = 0.0;
275 
276   for (size_t i = 0; i < arraysize(hs); i++) {
277     stime_t timeout = NO_DEADLINE;
278     wrapper.SyncInterpret(hs[i], &timeout);
279     stime_t next_input = i < (arraysize(hs) - 1) ? hs[i + 1].timestamp :
280         INFINITY;
281     stime_t now = hs[i].timestamp;
282     while (timeout >= 0 && (timeout + now) < next_input) {
283       now += timeout;
284       timeout = NO_DEADLINE;
285       wrapper.HandleTimer(now, &timeout);
286     }
287   }
288   EXPECT_EQ(3, base_interpreter->interpret_call_count_);
289   EXPECT_EQ(1, base_interpreter->finger_ids_.size());
290   EXPECT_EQ(1, *base_interpreter->finger_ids_.begin());
291 }
292 
293 class LookaheadFilterInterpreterNoTapSetTestInterpreter
294     : public Interpreter {
295  public:
LookaheadFilterInterpreterNoTapSetTestInterpreter()296   LookaheadFilterInterpreterNoTapSetTestInterpreter()
297       : Interpreter(nullptr, nullptr, false), interpret_call_count_(0) {}
298 
SyncInterpret(HardwareState & hwstate,stime_t * timeout)299   virtual void SyncInterpret(HardwareState& hwstate, stime_t* timeout) {
300     EXPECT_EQ(expected_finger_cnts_[interpret_call_count_], hwstate.finger_cnt);
301     interpret_call_count_++;
302     if (hwstate.finger_cnt > 0)
303       EXPECT_TRUE(hwstate.fingers[0].flags & GESTURES_FINGER_NO_TAP);
304   }
305 
HandleTimer(stime_t now,stime_t * timeout)306   virtual void HandleTimer(stime_t now, stime_t* timeout) {
307     FAIL() << "This interpreter doesn't use timers";
308   }
309 
310   std::set<short> finger_ids_;
311   size_t interpret_call_count_;
312   std::vector<short> expected_finger_cnts_;
313 };
314 
315 // Tests that with a zero delay, we can still avoid unnecessary splitting
316 // by using variable delay.
TEST(LookaheadFilterInterpreterTest,NoTapSetTest)317 TEST(LookaheadFilterInterpreterTest, NoTapSetTest) {
318   LookaheadFilterInterpreterNoTapSetTestInterpreter* base_interpreter =
319       new LookaheadFilterInterpreterNoTapSetTestInterpreter;
320   LookaheadFilterInterpreter interpreter(nullptr, base_interpreter, nullptr);
321   interpreter.min_delay_.val_ = 0.0;
322 
323   HardwareProperties initial_hwprops = {
324     .right = 100, .bottom = 100,
325     .res_x = 1,
326     .res_y = 1,
327     .screen_x_dpi = 0,
328     .screen_y_dpi = 0,
329     .orientation_minimum = -1,
330     .orientation_maximum = 2,
331     .max_finger_cnt = 5, .max_touch_cnt = 5,
332     .supports_t5r2 = 0, .support_semi_mt = 0, .is_button_pad = 0,
333     .has_wheel = 0, .wheel_is_hi_res = 0,
334     .is_haptic_pad = 0,
335   };
336 
337   FingerState fs[] = {
338     // TM, Tm, WM, Wm, pr, orient, x, y, id, flags
339     { 0, 0, 0, 0, 1, 0, 30, 10, 0, 0 },
340     { 0, 0, 0, 0, 1, 0, 30, 30, 0, 0 },
341     { 0, 0, 0, 0, 1, 0, 10, 10, 1, 0 },
342     { 0, 0, 0, 0, 1, 0, 10, 30, 1, 0 },
343   };
344   HardwareState hs[] = {
345     // Expect movement to take
346     make_hwstate(0.01, 0, 1, 1, &fs[0]),
347     make_hwstate(0.01, 0, 1, 1, &fs[1]),
348     make_hwstate(0.03, 0, 0, 0, nullptr),
349     make_hwstate(1.01, 0, 1, 1, &fs[2]),
350     make_hwstate(1.02, 0, 1, 1, &fs[3]),
351   };
352 
353   TestInterpreterWrapper wrapper(&interpreter, &initial_hwprops);
354 
355 
356   for (size_t i = 0; i < arraysize(hs); i++) {
357     base_interpreter->expected_finger_cnts_.push_back(hs[i].finger_cnt);
358     stime_t timeout = NO_DEADLINE;
359     interpreter.SyncInterpret(hs[i], &timeout);
360     stime_t next_input = i < (arraysize(hs) - 1) ? hs[i + 1].timestamp :
361         INFINITY;
362     stime_t now = hs[i].timestamp;
363     while (timeout >= 0 && (timeout + now) < next_input) {
364       now += timeout;
365       timeout = NO_DEADLINE;
366       interpreter.HandleTimer(now, &timeout);
367     }
368   }
369   EXPECT_EQ(arraysize(hs), base_interpreter->interpret_call_count_);
370 }
371 
372 // This test makes sure that if an interpreter requests a timeout, and then
373 // there is a spurious callback, that we request another callback for the time
374 // that remains.
TEST(LookaheadFilterInterpreterTest,SpuriousCallbackTest)375 TEST(LookaheadFilterInterpreterTest, SpuriousCallbackTest) {
376   LookaheadFilterInterpreterTestInterpreter* base_interpreter = nullptr;
377   std::unique_ptr<LookaheadFilterInterpreter> interpreter;
378 
379   HardwareProperties initial_hwprops = {
380     .right = 100, .bottom = 100,
381     .res_x = 10,
382     .res_y = 10,
383     .screen_x_dpi = 0,
384     .screen_y_dpi = 0,
385     .orientation_minimum = -1,
386     .orientation_maximum = 2,
387     .max_finger_cnt = 2, .max_touch_cnt = 5,
388     .supports_t5r2 = 1, .support_semi_mt = 0, .is_button_pad = 0,
389     .has_wheel = 0, .wheel_is_hi_res = 0,
390     .is_haptic_pad = 0,
391   };
392   TestInterpreterWrapper wrapper(interpreter.get(), &initial_hwprops);
393 
394   HardwareState hs = make_hwstate(1, 0, 0, 0, nullptr);
395 
396   base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
397   base_interpreter->timer_return_ = 1.0;
398   interpreter.reset(new LookaheadFilterInterpreter(
399       nullptr, base_interpreter, nullptr));
400   wrapper.Reset(interpreter.get());
401   interpreter->min_delay_.val_ = 0.05;
402 
403   stime_t timeout = NO_DEADLINE;
404   Gesture* out = wrapper.SyncInterpret(hs, &timeout);
405   EXPECT_EQ(nullptr, out);
406   EXPECT_FLOAT_EQ(interpreter->min_delay_.val_, timeout);
407 
408   out = wrapper.HandleTimer(hs.timestamp + interpreter->min_delay_.val_,
409                                  &timeout);
410   EXPECT_EQ(nullptr, out);
411   EXPECT_FLOAT_EQ(1.0, timeout);
412 
413 
414   out = wrapper.HandleTimer(hs.timestamp + interpreter->min_delay_.val_ +
415                                  0.25,
416                                  &timeout);
417   EXPECT_EQ(nullptr, out);
418   EXPECT_FLOAT_EQ(0.75, timeout);
419 }
420 
TEST(LookaheadFilterInterpreterTest,TimeGoesBackwardsTest)421 TEST(LookaheadFilterInterpreterTest, TimeGoesBackwardsTest) {
422   LookaheadFilterInterpreterTestInterpreter* base_interpreter =
423       new LookaheadFilterInterpreterTestInterpreter;
424   Gesture expected_movement = Gesture(kGestureMove,
425                                       0.0,  // start time
426                                       0.0,  // end time
427                                       1.0,  // dx
428                                       1.0);  // dy
429   base_interpreter->return_values_.push_back(expected_movement);
430   base_interpreter->return_values_.push_back(expected_movement);
431   LookaheadFilterInterpreter interpreter(nullptr, base_interpreter, nullptr);
432 
433   HardwareProperties initial_hwprops = {
434     .right = 100, .bottom = 100,
435     .res_x = 1,
436     .res_y = 1,
437     .screen_x_dpi = 0,
438     .screen_y_dpi = 0,
439     .orientation_minimum = -1,
440     .orientation_maximum = 2,
441     .max_finger_cnt = 2, .max_touch_cnt = 5,
442     .supports_t5r2 = 1, .support_semi_mt = 0, .is_button_pad = 0,
443     .has_wheel = 0, .wheel_is_hi_res = 0,
444     .is_haptic_pad = 0,
445   };
446   TestInterpreterWrapper wrapper(&interpreter, &initial_hwprops);
447 
448 
449   FingerState fs = {
450     // TM, Tm, WM, Wm, pr, orient, x, y, id
451     0, 0, 0, 0, 1, 0, 20, 20, 1, 0
452   };
453   HardwareState hs[] = {
454     // Initial state
455     make_hwstate(9.00, 0, 1, 1, &fs),
456     // Time jumps backwards, then goes forwards
457     make_hwstate(0.01, 0, 1, 1, &fs),
458     make_hwstate(0.02, 0, 1, 1, &fs),
459     make_hwstate(0.03, 0, 1, 1, &fs),
460     make_hwstate(0.04, 0, 1, 1, &fs),
461     make_hwstate(0.05, 0, 1, 1, &fs),
462     make_hwstate(0.06, 0, 1, 1, &fs),
463     make_hwstate(0.07, 0, 1, 1, &fs),
464     make_hwstate(0.08, 0, 1, 1, &fs),
465     make_hwstate(0.09, 0, 1, 1, &fs),
466     make_hwstate(0.10, 0, 1, 1, &fs),
467     make_hwstate(0.11, 0, 1, 1, &fs),
468     make_hwstate(0.12, 0, 1, 1, &fs),
469     make_hwstate(0.13, 0, 1, 1, &fs),
470     make_hwstate(0.14, 0, 1, 1, &fs),
471     make_hwstate(0.15, 0, 1, 1, &fs),
472     make_hwstate(0.16, 0, 1, 1, &fs),
473     make_hwstate(0.17, 0, 1, 1, &fs),
474     make_hwstate(0.18, 0, 1, 1, &fs),
475     make_hwstate(0.19, 0, 1, 1, &fs),
476     make_hwstate(0.20, 0, 1, 1, &fs),
477   };
478   for (size_t i = 0; i < arraysize(hs); ++i) {
479     stime_t timeout_requested = -1.0;
480     Gesture* result = wrapper.SyncInterpret(hs[i], &timeout_requested);
481     if (result && result->type == kGestureTypeMove)
482       return;  // Success!
483   }
484   ADD_FAILURE() << "Should have gotten a move gesture";
485 }
486 
TEST(LookaheadFilterInterpreterTest,InterpolateHwStateTest)487 TEST(LookaheadFilterInterpreterTest, InterpolateHwStateTest) {
488   // This test takes the first two HardwareStates, Interpolates them, putting
489   // the output into the fourth slot. The third slot is the expected output.
490   FingerState fs[] = {
491     // TM, Tm, WM, Wm, pr, orient, x, y, id
492     { 0.1, 0.4, 1.6, 1.2, 10, 3, 102, 102, 1, 0 },
493     { 0.2, 0.5, 1.7, 1.3, 11, 4, 4, 4, 2, 0 },
494     { 0.3, 0.6, 1.8, 1.4, 12, 5, 4444, 9999, 3, 0 },
495 
496     { 0.5, 0.2, 2.0, 1.2, 13, 8, 200, 100, 1, 0 },
497     { 0.7, 0.4, 2.3, 1.3, 17, 7, 20, 22, 2, 0 },
498     { 1.0, 0.5, 2.4, 1.6, 10, 9, 5000, 5000, 3, 0 },
499 
500     { 0.3, 0.3, 1.8, 1.2, 11.5, 5.5, 151, 101, 1, 0 },
501     { 0.45, 0.45, 2.0, 1.3, 14, 5.5, 12, 13, 2, 0 },
502     { 0.65, 0.55, 2.1, 1.5, 11, 7, 4722, 7499.5, 3, 0 },
503 
504     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
505     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
506     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
507   };
508   HardwareState hs[] = {
509     // Expect movement to take
510     make_hwstate(1.011,  2, 3, 3, &fs[0]),
511     make_hwstate(1.022,  2, 3, 3, &fs[3]),
512     make_hwstate(1.0165, 2, 3, 3, &fs[6]),
513     make_hwstate(0, 0, 0, 0, &fs[9]),
514   };
515 
516   LookaheadFilterInterpreter::Interpolate(hs[0], hs[1], &hs[3]);
517   EXPECT_DOUBLE_EQ(hs[2].timestamp, hs[3].timestamp);
518   EXPECT_EQ(hs[2].buttons_down, hs[3].buttons_down);
519   EXPECT_EQ(hs[2].touch_cnt, hs[3].touch_cnt);
520   EXPECT_EQ(hs[2].finger_cnt, hs[3].finger_cnt);
521   for (size_t i = 0; i < hs[3].finger_cnt; i++)
522     EXPECT_TRUE(hs[2].fingers[i] == hs[3].fingers[i]) << "i=" << i;
523 }
524 
TEST(LookaheadFilterInterpreterTest,InterpolateTest)525 TEST(LookaheadFilterInterpreterTest, InterpolateTest) {
526   LookaheadFilterInterpreterTestInterpreter* base_interpreter = nullptr;
527   std::unique_ptr<LookaheadFilterInterpreter> interpreter;
528 
529   HardwareProperties initial_hwprops = {
530     .right = 100, .bottom = 100,
531     .res_x = 10,
532     .res_y = 10,
533     .screen_x_dpi = 0,
534     .screen_y_dpi = 0,
535     .orientation_minimum = -1,
536     .orientation_maximum = 2,
537     .max_finger_cnt = 2, .max_touch_cnt = 5,
538     .supports_t5r2 = 1, .support_semi_mt = 0, .is_button_pad = 0,
539     .has_wheel = 0, .wheel_is_hi_res = 0,
540     .is_haptic_pad = 0,
541   };
542   TestInterpreterWrapper wrapper(interpreter.get(), &initial_hwprops);
543 
544   FingerState fs = {
545     // TM, Tm, WM, Wm, pr, orient, x, y, id
546     0, 0, 0, 0, 1, 0, 10, 1, 1, 0
547   };
548   HardwareState hs[] = {
549     // Expect movement to take
550     make_hwstate(1.01, 0, 1, 1, &fs),
551     make_hwstate(1.02, 0, 1, 1, &fs),
552     make_hwstate(1.04, 0, 1, 1, &fs),
553   };
554 
555   // Tests that we can properly decide when to interpolate two events.
556   for (size_t i = 0; i < 2; ++i) {
557     bool should_interpolate = i;
558     base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
559     base_interpreter->clear_incoming_hwstates_ = true;
560     base_interpreter->return_values_.push_back(
561         Gesture(kGestureMove,
562                 0,  // start time
563                 1,  // end time
564                 0,  // dx
565                 1));  // dy
566     base_interpreter->return_values_.push_back(
567         Gesture(kGestureMove,
568                 1,  // start time
569                 2,  // end time
570                 0,  // dx
571                 2));  // dy
572     base_interpreter->return_values_.push_back(
573         Gesture(kGestureMove,
574                 2,  // start time
575                 3,  // end time
576                 0,  // dx
577                 3));  // dy
578     interpreter.reset(new LookaheadFilterInterpreter(
579         nullptr, base_interpreter, nullptr));
580     wrapper.Reset(interpreter.get());
581     interpreter->min_delay_.val_ = 0.05;
582 
583     stime_t timeout = NO_DEADLINE;
584     Gesture* out = wrapper.SyncInterpret(hs[0], &timeout);
585     EXPECT_EQ(nullptr, out);
586     EXPECT_GT(timeout, 0);
587     const size_t next_idx = should_interpolate ? 2 : 1;
588     timeout = NO_DEADLINE;
589     out = wrapper.SyncInterpret(hs[next_idx], &timeout);
590     EXPECT_EQ(nullptr, out);
591     EXPECT_GT(timeout, 0);
592 
593     // Fetch the gestures
594     size_t gs_count = 0;
595     stime_t now = hs[next_idx].timestamp + timeout;
596     do {
597       timeout = NO_DEADLINE;
598       out = wrapper.HandleTimer(now, &timeout);
599       EXPECT_NE(nullptr, out);
600       gs_count++;
601       now += timeout;
602     } while(timeout > 0.0);
603     EXPECT_EQ(should_interpolate ? 3 : 2, gs_count);
604   }
605 }
606 
TEST(LookaheadFilterInterpreterTest,InterpolationOverdueTest)607 TEST(LookaheadFilterInterpreterTest, InterpolationOverdueTest) {
608   LookaheadFilterInterpreterTestInterpreter* base_interpreter = nullptr;
609   std::unique_ptr<LookaheadFilterInterpreter> interpreter;
610 
611   HardwareProperties initial_hwprops = {
612     .right = 10, .bottom = 10,
613     .res_x = 1,
614     .res_y = 1,
615     .screen_x_dpi = 0,
616     .screen_y_dpi = 0,
617     .orientation_minimum = -1,
618     .orientation_maximum = 2,
619     .max_finger_cnt = 2, .max_touch_cnt = 5,
620     .supports_t5r2 = 1, .support_semi_mt = 0, .is_button_pad = 0,
621     .has_wheel = 0, .wheel_is_hi_res = 0,
622     .is_haptic_pad = 0,
623   };
624   TestInterpreterWrapper wrapper(interpreter.get(), &initial_hwprops);
625 
626   FingerState fs = {
627     // TM, Tm, WM, Wm, pr, orient, x, y, id
628     0, 0, 0, 0, 1, 0, 10, 1, 1, 0
629   };
630   // These timestamps cause an interpolated event to be 1.492 at time 1.495,
631   // and so this tests that an overdue interpolated event is handled correctly.
632   HardwareState hs[] = {
633     // Expect movement to take
634     make_hwstate(1.456, 0, 1, 1, &fs),
635     make_hwstate(1.495, 0, 1, 1, &fs),
636   };
637 
638   base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
639   base_interpreter->timer_return_ = 0.700;
640   base_interpreter->return_values_.push_back(
641       Gesture(kGestureMove,
642               0,  // start time
643               1,  // end time
644               0,  // dx
645               1));  // dy
646   base_interpreter->return_values_.push_back(
647       Gesture(kGestureMove,
648               1,  // start time
649               2,  // end time
650               0,  // dx
651               2));  // dy
652   interpreter.reset(new LookaheadFilterInterpreter(
653       nullptr, base_interpreter, nullptr));
654   interpreter->min_delay_.val_ = 0.017;
655   wrapper.Reset(interpreter.get());
656 
657   stime_t timeout = NO_DEADLINE;
658   Gesture* out = wrapper.SyncInterpret(hs[0], &timeout);
659   EXPECT_EQ(nullptr, out);
660   EXPECT_FLOAT_EQ(timeout, interpreter->min_delay_.val_);
661 
662   stime_t now = hs[0].timestamp + timeout;
663   timeout = NO_DEADLINE;
664   out = wrapper.HandleTimer(now, &timeout);
665   ASSERT_NE(nullptr, out);
666   EXPECT_EQ(kGestureTypeMove, out->type);
667   EXPECT_EQ(1, out->details.move.dy);
668   EXPECT_DOUBLE_EQ(timeout, 0.700);
669 
670   timeout = NO_DEADLINE;
671   out = wrapper.SyncInterpret(hs[1], &timeout);
672   ASSERT_NE(nullptr, out);
673   EXPECT_EQ(kGestureTypeMove, out->type);
674   EXPECT_EQ(2, out->details.move.dy);
675   EXPECT_GE(timeout, 0.0);
676 }
677 
678 struct HardwareStateLastId {
679   HardwareState hs;
680   short expected_last_id;
681 };
682 
TEST(LookaheadFilterInterpreterTest,DrumrollTest)683 TEST(LookaheadFilterInterpreterTest, DrumrollTest) {
684   LookaheadFilterInterpreterTestInterpreter* base_interpreter = nullptr;
685   std::unique_ptr<LookaheadFilterInterpreter> interpreter;
686 
687   HardwareProperties initial_hwprops = {
688     .right = 100, .bottom = 100,
689     .res_x = 1,
690     .res_y = 1,
691     .screen_x_dpi = 0,
692     .screen_y_dpi = 0,
693     .orientation_minimum = -1,
694     .orientation_maximum = 2,
695     .max_finger_cnt = 2, .max_touch_cnt = 5,
696     .supports_t5r2 = 1, .support_semi_mt = 0, .is_button_pad = 0,
697     .has_wheel = 0, .wheel_is_hi_res = 0,
698     .is_haptic_pad = 0,
699   };
700   TestInterpreterWrapper wrapper(interpreter.get(), &initial_hwprops);
701 
702   FingerState fs[] = {
703     // TM, Tm, WM, Wm, pr, orient, x, y, id
704     { 0, 0, 0, 0, 1, 0, 40, 40, 1, 0 },
705     { 0, 0, 0, 0, 1, 0, 40, 80, 1, 0 },
706     { 0, 0, 0, 0, 1, 0, 40, 40, 2, 0 },
707     { 0, 0, 0, 0, 1, 0, 41, 80, 2, 0 },
708     // Warp cases:
709     { 0, 0, 0, 0, 1, 0, 40, 40, 3, 0 },
710     { 0, 0, 0, 0, 1, 0, 41, 80, 3, GESTURES_FINGER_WARP_X },
711     { 0, 0, 0, 0, 1, 0, 40, 40, 4, 0 },
712     { 0, 0, 0, 0, 1, 0, 41, 80, 4, GESTURES_FINGER_WARP_Y },
713     { 0, 0, 0, 0, 1, 0, 40, 40, 5, 0 },
714     { 0, 0, 0, 0, 1, 0, 41, 80, 5, GESTURES_FINGER_WARP_X |
715                                    GESTURES_FINGER_WARP_Y },
716   };
717   // These timestamps cause an interpolated event to be 1.492 at time 1.495,
718   // and so this tests that an overdue interpolated event is handled correctly.
719   HardwareStateLastId hsid[] = {
720     // Expect movement to take
721     { make_hwstate(1.000, 0, 1, 1, &fs[0]), 1 },
722     { make_hwstate(1.001, 0, 1, 1, &fs[0]), 1 },
723     { make_hwstate(1.002, 0, 1, 1, &fs[1]), 2 },
724     { make_hwstate(1.003, 0, 1, 1, &fs[1]), 2 },
725     { make_hwstate(1.004, 0, 1, 1, &fs[2]), 3 },
726     { make_hwstate(1.005, 0, 1, 1, &fs[3]), 4 },
727     { make_hwstate(1.006, 0, 1, 1, &fs[2]), 5 },
728     // Warp cases:
729     { make_hwstate(1.007, 0, 1, 1, &fs[4]), 6 },
730     { make_hwstate(1.008, 0, 1, 1, &fs[5]), 6 },
731     { make_hwstate(1.009, 0, 1, 1, &fs[6]), 7 },
732     { make_hwstate(1.010, 0, 1, 1, &fs[7]), 7 },
733     { make_hwstate(1.011, 0, 1, 1, &fs[8]), 8 },
734     { make_hwstate(1.012, 0, 1, 1, &fs[9]), 8 },
735   };
736 
737   base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
738   base_interpreter->return_values_.push_back(
739       Gesture(kGestureMove,
740               0,  // start time
741               1,  // end time
742               0,  // dx
743               1));  // dy
744   interpreter.reset(new LookaheadFilterInterpreter(
745       nullptr, base_interpreter, nullptr));
746   wrapper.Reset(interpreter.get());
747 
748   for (size_t i = 0; i < arraysize(hsid); i++) {
749     stime_t timeout = NO_DEADLINE;
750     Gesture* out = wrapper.SyncInterpret(hsid[i].hs, &timeout);
751     if (out) {
752       EXPECT_EQ(kGestureTypeFling, out->type);
753       EXPECT_EQ(GESTURES_FLING_TAP_DOWN, out->details.fling.fling_state);
754     }
755     EXPECT_GT(timeout, 0);
756     EXPECT_EQ(interpreter->last_id_, hsid[i].expected_last_id);
757   }
758 }
759 
TEST(LookaheadFilterInterpreterTest,QuickMoveTest)760 TEST(LookaheadFilterInterpreterTest, QuickMoveTest) {
761   LookaheadFilterInterpreterTestInterpreter* base_interpreter = nullptr;
762   std::unique_ptr<LookaheadFilterInterpreter> interpreter;
763 
764   HardwareProperties initial_hwprops = {
765     .right = 100, .bottom = 100,
766     .res_x = 1,
767     .res_y = 1,
768     .screen_x_dpi = 0,
769     .screen_y_dpi = 0,
770     .orientation_minimum = -1,
771     .orientation_maximum = 2,
772     .max_finger_cnt = 2, .max_touch_cnt = 5,
773     .supports_t5r2 = 1, .support_semi_mt = 0, .is_button_pad = 0,
774     .has_wheel = 0, .wheel_is_hi_res = 0,
775     .is_haptic_pad = 0,
776   };
777   TestInterpreterWrapper wrapper(interpreter.get(), &initial_hwprops);
778 
779   FingerState fs[] = {
780     // TM, Tm, WM, Wm, pr, orient, x, y, id
781     { 0, 0, 0, 0, 1, 0, 40, 40, 1, 0 },
782     { 0, 0, 0, 0, 1, 0, 41, 80, 1, 0 },
783     { 0, 0, 0, 0, 1, 0, 40, 40, 1, 0 },
784 
785     { 0, 0, 0, 0, 1, 0, 40, 40, 2, 0 },
786     { 0, 0, 0, 0, 1, 0, 41, 80, 2, 0 },
787     { 0, 0, 0, 0, 1, 0, 40, 120, 2, 0 },
788   };
789 
790   HardwareState hs[] = {
791     // Drumroll
792     make_hwstate(1.000, 0, 1, 1, &fs[0]),
793     make_hwstate(1.001, 0, 1, 1, &fs[1]),
794     make_hwstate(1.002, 0, 1, 1, &fs[2]),
795     // No touch
796     make_hwstate(1.003, 0, 0, 0, &fs[0]),
797     // Quick movement
798     make_hwstate(1.034, 0, 1, 1, &fs[3]),
799     make_hwstate(1.035, 0, 1, 1, &fs[4]),
800     make_hwstate(1.036, 0, 1, 1, &fs[5]),
801   };
802 
803   base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
804   interpreter.reset(new LookaheadFilterInterpreter(
805       nullptr, base_interpreter, nullptr));
806   wrapper.Reset(interpreter.get());
807 
808   stime_t timeout = NO_DEADLINE;
809   const auto& queue = interpreter->queue_;
810 
811   // Pushing the first event
812   wrapper.SyncInterpret(hs[0], &timeout);
813   EXPECT_EQ(queue.size(), 1);
814   EXPECT_EQ(queue.back().fs_[0].tracking_id, 1);
815 
816   // Expecting Drumroll detected and ID reassigned 1 -> 2.
817   wrapper.SyncInterpret(hs[1], &timeout);
818   EXPECT_EQ(queue.size(), 2);
819   EXPECT_EQ(queue.back().fs_[0].tracking_id, 2);
820 
821   // Expecting Drumroll detected and ID reassigned 1 -> 3.
822   wrapper.SyncInterpret(hs[2], &timeout);
823   EXPECT_EQ(queue.size(), 3);
824   EXPECT_EQ(queue.back().fs_[0].tracking_id, 3);
825 
826   // Removing the touch.
827   wrapper.SyncInterpret(hs[3], &timeout);
828   EXPECT_EQ(queue.size(), 4);
829 
830   // New event comes, old events removed from the queue.
831   // New finger tracking ID assigned 2 - > 4.
832   wrapper.SyncInterpret(hs[4], &timeout);
833   EXPECT_EQ(queue.size(), 2);
834   EXPECT_EQ(queue.back().fs_[0].tracking_id, 4);
835 
836   // Expecting Drumroll detected and ID reassigned 2 -> 5.
837   wrapper.SyncInterpret(hs[5], &timeout);
838   EXPECT_EQ(queue.back().fs_[0].tracking_id, 5);
839 
840   // Expecting Quick movement detected and ID correction 5 -> 4.
841   wrapper.SyncInterpret(hs[6], &timeout);
842   EXPECT_EQ(interpreter->queue_.at(-1).fs_[0].tracking_id, 4);
843   EXPECT_EQ(interpreter->queue_.at(-2).fs_[0].tracking_id, 4);
844   EXPECT_EQ(interpreter->queue_.at(-3).fs_[0].tracking_id, 4);
845 }
846 
847 struct QuickSwipeTestInputs {
848   stime_t now;
849   float x0, y0, pressure0;
850   short id0;
851   float x1, y1, pressure1;
852   short id1;
853 };
854 
855 // Based on a couple quick swipes of 2 fingers on Alex, makes sure that we
856 // don't drumroll-separate the fingers.
TEST(LookaheadFilterInterpreterTest,QuickSwipeTest)857 TEST(LookaheadFilterInterpreterTest, QuickSwipeTest) {
858   LookaheadFilterInterpreterTestInterpreter* base_interpreter = nullptr;
859   std::unique_ptr<LookaheadFilterInterpreter> interpreter;
860 
861   HardwareProperties initial_hwprops = {
862     .right = 95.934784,
863     .bottom = 65.259262,
864     .res_x = 1.000000,
865     .res_y = 1.000000,
866     .screen_x_dpi = 0,
867     .screen_y_dpi = 0,
868     .orientation_minimum = -1,
869     .orientation_maximum = 2,
870     .max_finger_cnt = 2,
871     .max_touch_cnt = 5,
872     .supports_t5r2 = 1,
873     .support_semi_mt = 0,
874     .is_button_pad = 1,
875     .has_wheel = 0,
876     .wheel_is_hi_res = 0,
877     .is_haptic_pad = 0,
878   };
879   TestInterpreterWrapper wrapper(interpreter.get(), &initial_hwprops);
880 
881   // Actual data captured from Alex
882   QuickSwipeTestInputs inputs[] = {
883     // Two fingers arriving at the same time doing a swipe
884     { 6.30188, 50.34, 53.29, 22.20, 91, 33.28, 56.05, 22.20, 92 },
885     { 6.33170, 55.13, 32.40, 31.85, 91, 35.02, 42.20, 28.63, 92 },
886 
887     // Two fingers doing a swipe, but one arrives a few frames before
888     // the other
889     { 84.602478, 35.41, 65.27,  7.71, 93, -1.00, -1.00, -1.00, -1 },
890     { 84.641174, 38.17, 43.07, 31.85, 93, -1.00, -1.00, -1.00, -1 },
891     { 84.666290, 42.78, 21.66, 35.07, 93, 61.36, 31.83, 22.20, 94 },
892     { 84.690422, 50.43,  5.37, 15.75, 93, 66.93, 12.64, 28.63, 94 },
893   };
894 
895   base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
896   interpreter.reset(new LookaheadFilterInterpreter(
897       nullptr, base_interpreter, nullptr));
898   wrapper.Reset(interpreter.get());
899 
900   interpreter->min_delay_.val_ = 0.017;
901   interpreter->max_delay_.val_ = 0.026;
902 
903   // Prime it w/ a dummy hardware state
904   stime_t timeout = NO_DEADLINE;
905   HardwareState temp_hs = make_hwstate(0.000001, 0, 0, 0, nullptr);
906   wrapper.SyncInterpret(temp_hs, &timeout);
907   wrapper.HandleTimer(temp_hs.timestamp + timeout, nullptr);
908 
909   std::set<short> input_ids;
910 
911   for (size_t i = 0; i < arraysize(inputs); i++) {
912     const QuickSwipeTestInputs& in = inputs[i];
913     FingerState fs[] = {
914       // TM, Tm, WM, Wm, pr, orient, x, y, id, flags
915       { 0, 0, 0, 0, in.pressure0, 0, in.x0, in.y0, in.id0, 0 },
916       { 0, 0, 0, 0, in.pressure1, 0, in.x1, in.y1, in.id1, 0 },
917     };
918     unsigned short finger_cnt = in.id0 < 0 ? 0 : (in.id1 < 0 ? 1 : 2);
919     HardwareState hs = make_hwstate(in.now, 0, finger_cnt, finger_cnt, fs);
920 
921     for (size_t idx = 0; idx < finger_cnt; idx++)
922       input_ids.insert(fs[idx].tracking_id);
923 
924     stime_t timeout = NO_DEADLINE;
925     wrapper.SyncInterpret(hs, &timeout);
926     if (timeout >= 0) {
927       stime_t next_timestamp = INFINITY;
928       if (i < arraysize(inputs) - 1)
929         next_timestamp = inputs[i + 1].now;
930       stime_t now = in.now;
931       while (timeout >= 0 && (now + timeout) < next_timestamp) {
932         now += timeout;
933         timeout = NO_DEADLINE;
934         wrapper.HandleTimer(now, &timeout);
935       }
936     }
937   }
938 
939   EXPECT_EQ(input_ids.size(), base_interpreter->all_ids_.size());
940 }
941 
942 struct CyapaDrumrollTestInputs {
943   bool reset_;
944   stime_t now_;
945   float x_, y_, pressure_;
946   unsigned flags_;
947   bool jump_here_;
948 };
949 
950 // Replays a couple instances of drumroll from a Cyapa system as reported by
951 // Doug Anderson.
TEST(LookaheadFilterInterpreterTest,CyapaDrumrollTest)952 TEST(LookaheadFilterInterpreterTest, CyapaDrumrollTest) {
953   LookaheadFilterInterpreterTestInterpreter* base_interpreter = nullptr;
954   std::unique_ptr<LookaheadFilterInterpreter> interpreter;
955 
956   HardwareProperties initial_hwprops = {
957     .right = 106.666672,
958     .bottom = 68.000000,
959     .res_x = 1.000000,
960     .res_y = 1.000000,
961     .screen_x_dpi = 0,
962     .screen_y_dpi = 0,
963     .orientation_minimum = -1,
964     .orientation_maximum = 2,
965     .max_finger_cnt = 15,
966     .max_touch_cnt = 5,
967     .supports_t5r2 = 0,
968     .support_semi_mt = 0,
969     .is_button_pad = 0,
970     .has_wheel = 0,
971     .wheel_is_hi_res = 0,
972     .is_haptic_pad = 0,
973   };
974   TestInterpreterWrapper wrapper(interpreter.get(), &initial_hwprops);
975 
976   CyapaDrumrollTestInputs inputs[] = {
977     // First run:
978     { true,  3.39245, 67.83, 34.10,  3.71, 0, false },
979     { false, 3.40097, 67.83, 34.10, 30.88, 0, false },
980     { false, 3.40970, 67.83, 34.10, 42.52, 0, false },
981     { false, 3.44442, 67.83, 34.40, 44.46, 0, false },
982     { false, 3.45307, 67.83, 34.60, 44.46, 0, false },
983     { false, 3.46176, 67.83, 34.79, 44.46, 0, false },
984     { false, 3.47041, 68.16, 35.20, 46.40, 0, false },
985     { false, 3.47929, 68.83, 35.60, 50.28, 0, false },
986     { false, 3.48806, 69.25, 35.90, 50.28, 0, false },
987     { false, 3.49700, 69.75, 36.10, 52.22, 0, false },
988     { false, 3.50590, 70.08, 36.50, 50.28, 0, false },
989     { false, 3.51464, 70.41, 36.60, 52.22, 0, false },
990     { false, 3.52355, 70.75, 36.79, 52.22, 0, false },
991     { false, 3.53230, 71.00, 36.90, 52.22, 0, false },
992     { false, 3.54118, 71.16, 36.90, 50.28, 0, false },
993     { false, 3.55004, 71.33, 36.90, 52.22, 0, false },
994     { false, 3.55900, 71.58, 37.10, 54.16, 0, false },
995     { false, 3.56801, 71.66, 37.10, 52.22, 0, false },
996     { false, 3.57690, 71.83, 37.10, 54.16, 0, false },
997     { false, 3.59494, 71.91, 37.10, 52.22, 0, false },
998     { false, 3.63092, 72.00, 37.10, 54.16, 0, false },
999     { false, 3.68472, 72.00, 37.10, 56.10, 0, false },
1000     { false, 3.70275, 72.00, 37.10, 54.16, 0, false },
1001     { false, 3.71167, 72.00, 37.10, 52.22, 0, false },
1002     { false, 3.72067, 72.00, 37.10, 50.28, 0, false },
1003     { false, 3.72959, 72.00, 37.10, 42.52, 0, false },
1004     { false, 3.73863, 72.00, 37.10, 27.00, 0, false },
1005     // jump occurs here:
1006     { false, 3.74794, 14.58, 67.70, 17.30, 2, true },
1007     { false, 3.75703, 13.91, 66.59, 48.34, 2, false },
1008     { false, 3.76619, 13.91, 66.59, 50.28, 0, false },
1009     { false, 3.77531, 13.91, 66.20, 58.04, 0, false },
1010     { false, 3.78440, 13.91, 66.20, 58.04, 0, false },
1011     { false, 3.80272, 13.91, 66.00, 59.99, 0, false },
1012     { false, 3.81203, 13.91, 66.00, 61.93, 0, false },
1013     { false, 3.83017, 13.91, 66.00, 61.93, 0, false },
1014     { false, 3.83929, 13.91, 65.80, 61.93, 0, false },
1015     { false, 3.84849, 13.91, 65.70, 61.93, 0, false },
1016     { false, 3.90325, 13.91, 65.70, 59.99, 0, false },
1017     { false, 3.91247, 13.91, 65.70, 56.10, 0, false },
1018     { false, 3.92156, 13.91, 65.70, 42.52, 0, false },
1019     // Second run:
1020     { true,  39.25706, 91.08, 26.70, 25.06, 0, false },
1021     { false, 39.26551, 91.08, 26.70, 32.82, 0, false },
1022     { false, 39.27421, 89.66, 26.70, 34.76, 1, false },
1023     { false, 39.28285, 88.50, 26.70, 38.64, 1, false },
1024     { false, 39.29190, 87.75, 26.70, 42.52, 0, false },
1025     { false, 39.30075, 86.66, 26.70, 44.46, 0, false },
1026     { false, 39.30940, 85.66, 26.70, 44.46, 0, false },
1027     { false, 39.31812, 83.91, 26.70, 44.46, 0, false },
1028     { false, 39.32671, 82.25, 26.40, 48.34, 0, false },
1029     { false, 39.33564, 80.66, 26.30, 48.34, 0, false },
1030     { false, 39.34467, 79.25, 26.10, 50.28, 0, false },
1031     { false, 39.35335, 77.41, 26.00, 48.34, 0, false },
1032     { false, 39.36222, 75.50, 25.80, 52.22, 0, false },
1033     { false, 39.37135, 74.25, 25.80, 54.16, 0, false },
1034     { false, 39.38032, 73.25, 25.80, 56.10, 0, false },
1035     { false, 39.38921, 71.91, 25.80, 52.22, 0, false },
1036     { false, 39.39810, 70.25, 25.80, 56.10, 0, false },
1037     { false, 39.40708, 68.75, 25.80, 58.04, 0, false },
1038     { false, 39.41612, 67.75, 25.80, 59.99, 0, false },
1039     { false, 39.42528, 66.83, 25.70, 61.93, 0, false },
1040     { false, 39.43439, 66.25, 25.70, 58.04, 0, false },
1041     { false, 39.44308, 65.33, 25.70, 58.04, 0, false },
1042     { false, 39.45196, 64.41, 25.70, 59.99, 0, false },
1043     { false, 39.46083, 63.75, 25.70, 59.99, 0, false },
1044     { false, 39.46966, 63.25, 25.70, 61.93, 0, false },
1045     { false, 39.47855, 62.83, 25.70, 65.81, 0, false },
1046     { false, 39.48741, 62.50, 25.70, 63.87, 0, false },
1047     { false, 39.49632, 62.00, 25.70, 63.87, 0, false },
1048     { false, 39.50527, 61.66, 25.70, 61.93, 0, false },
1049     { false, 39.51422, 61.41, 25.70, 61.93, 0, false },
1050     { false, 39.52323, 61.08, 25.70, 63.87, 0, false },
1051     { false, 39.54126, 61.00, 25.70, 65.81, 0, false },
1052     { false, 39.55042, 60.83, 25.70, 65.81, 0, false },
1053     { false, 39.55951, 60.75, 25.70, 65.81, 0, false },
1054     { false, 39.56852, 60.33, 25.70, 63.87, 0, false },
1055     { false, 39.57756, 60.00, 25.70, 63.87, 0, false },
1056     { false, 39.58664, 59.58, 25.70, 63.87, 0, false },
1057     { false, 39.59553, 59.08, 25.70, 63.87, 0, false },
1058     { false, 39.60432, 58.50, 25.70, 67.75, 0, false },
1059     { false, 39.61319, 57.75, 25.70, 67.75, 0, false },
1060     { false, 39.62219, 57.33, 25.70, 67.75, 0, false },
1061     { false, 39.63088, 56.83, 25.70, 67.75, 0, false },
1062     { false, 39.63976, 56.33, 25.70, 67.75, 0, false },
1063     { false, 39.64860, 55.83, 25.70, 67.75, 0, false },
1064     { false, 39.65758, 55.33, 25.70, 65.81, 0, false },
1065     { false, 39.66647, 54.83, 25.70, 65.81, 0, false },
1066     { false, 39.67554, 54.33, 26.00, 69.69, 0, false },
1067     { false, 39.68430, 53.75, 26.10, 67.75, 0, false },
1068     { false, 39.69313, 53.33, 26.40, 67.75, 0, false },
1069     { false, 39.70200, 52.91, 26.40, 67.75, 0, false },
1070     { false, 39.71106, 52.33, 26.60, 67.75, 0, false },
1071     { false, 39.71953, 51.83, 26.80, 69.69, 0, false },
1072     { false, 39.72814, 51.41, 26.80, 71.63, 0, false },
1073     { false, 39.73681, 50.75, 26.80, 71.63, 0, false },
1074     { false, 39.74569, 50.33, 26.80, 71.63, 0, false },
1075     { false, 39.75422, 49.83, 26.80, 73.57, 0, false },
1076     { false, 39.76303, 49.33, 26.80, 75.51, 0, false },
1077     { false, 39.77166, 49.00, 26.80, 73.57, 0, false },
1078     { false, 39.78054, 48.41, 26.80, 75.51, 0, false },
1079     { false, 39.78950, 48.16, 26.80, 75.51, 0, false },
1080     { false, 39.79827, 47.83, 26.80, 75.51, 0, false },
1081     { false, 39.80708, 47.58, 26.80, 77.45, 0, false },
1082     { false, 39.81598, 47.41, 26.80, 77.45, 0, false },
1083     { false, 39.82469, 47.33, 26.80, 75.51, 0, false },
1084     { false, 39.83359, 47.25, 26.80, 75.51, 0, false },
1085     { false, 39.84252, 47.25, 26.80, 77.45, 0, false },
1086     { false, 39.87797, 47.25, 26.80, 75.51, 0, false },
1087     { false, 39.88674, 47.25, 26.80, 71.63, 0, false },
1088     { false, 39.89573, 47.25, 26.80, 67.75, 0, false },
1089     { false, 39.90444, 47.25, 26.80, 52.22, 0, false },
1090     { false, 39.91334, 47.25, 26.80, 27.00, 0, false },
1091     { false, 39.92267, 21.00, 62.29, 34.76, 1, true },
1092     { false, 39.93177, 21.00, 62.50, 46.40, 0, false },
1093     { false, 39.94127, 21.00, 62.79, 56.10, 2, false },
1094     { false, 39.95053, 21.00, 62.79, 61.93, 0, false },
1095     { false, 39.96006, 21.00, 62.79, 63.87, 0, false },
1096     { false, 39.96919, 21.00, 62.79, 65.81, 0, false },
1097     { false, 39.97865, 21.00, 62.79, 67.75, 0, false },
1098     { false, 39.99727, 21.00, 62.79, 67.75, 0, false },
1099     { false, 40.00660, 21.00, 62.79, 67.75, 0, false },
1100     { false, 40.02541, 21.00, 62.60, 67.75, 0, false },
1101     { false, 40.04417, 21.00, 62.60, 65.81, 0, false },
1102     { false, 40.05345, 21.00, 62.60, 63.87, 0, false },
1103     { false, 40.06241, 21.00, 62.60, 58.04, 0, false },
1104     { false, 40.07105, 21.00, 60.90, 34.76, 2, false },
1105     { false, 40.07990, 21.16, 59.10,  5.65, 2, false },
1106   };
1107 
1108   for (size_t i = 0; i < arraysize(inputs); i++) {
1109     const CyapaDrumrollTestInputs& input = inputs[i];
1110     FingerState fs = {
1111       // TM, Tm, WM, Wm, pr, orient, x, y, id, flags
1112       0, 0, 0, 0, input.pressure_, 0, input.x_, input.y_, 1, input.flags_
1113     };
1114     HardwareState hs = make_hwstate(input.now_, 0, 1, 1, &fs);
1115     if (input.reset_) {
1116       if (base_interpreter) {
1117         EXPECT_TRUE(base_interpreter->expected_flags_at_occurred_);
1118       }
1119       base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
1120       base_interpreter->expected_id_ = 1;
1121       interpreter.reset(new LookaheadFilterInterpreter(
1122           nullptr, base_interpreter, nullptr));
1123       wrapper.Reset(interpreter.get());
1124     }
1125     if (input.jump_here_) {
1126       base_interpreter->expected_flags_ =
1127           GESTURES_FINGER_WARP_X | GESTURES_FINGER_WARP_Y;
1128       base_interpreter->expected_flags_at_ = input.now_;
1129     }
1130     stime_t timeout = NO_DEADLINE;
1131     wrapper.SyncInterpret(hs, &timeout);
1132     if (timeout >= 0) {
1133       stime_t next_timestamp = INFINITY;
1134       if (i < arraysize(inputs) - 1)
1135         next_timestamp = inputs[i + 1].now_;
1136       stime_t now = input.now_;
1137       while (timeout >= 0 && (now + timeout) < next_timestamp) {
1138         now += timeout;
1139         timeout = NO_DEADLINE;
1140         wrapper.HandleTimer(now, &timeout);
1141       }
1142     }
1143   }
1144   ASSERT_TRUE(base_interpreter);
1145   EXPECT_TRUE(base_interpreter->expected_flags_at_occurred_);
1146 }
1147 
1148 struct CyapaQuickTwoFingerMoveTestInputs {
1149   stime_t now;
1150   float x0, y0, pressure0;
1151   float x1, y1, pressure1;
1152   float x2, y2, pressure2;
1153 };
1154 
1155 // Using data from a real log, tests that when we do a swipe with large delay
1156 // on Lumpy, we don't reassign finger IDs b/c we use sufficient temporary
1157 // delay.
TEST(LookaheadFilterInterpreterTest,CyapaQuickTwoFingerMoveTest)1158 TEST(LookaheadFilterInterpreterTest, CyapaQuickTwoFingerMoveTest) {
1159   LookaheadFilterInterpreterTestInterpreter* base_interpreter =
1160       new LookaheadFilterInterpreterTestInterpreter;
1161   LookaheadFilterInterpreter interpreter(nullptr, base_interpreter, nullptr);
1162   interpreter.min_delay_.val_ = 0.0;
1163 
1164   HardwareProperties initial_hwprops = {
1165     .right = 106.666672,
1166     .bottom = 68.000000,
1167     .res_x = 1.000000,
1168     .res_y = 1.000000,
1169     .screen_x_dpi = 0,
1170     .screen_y_dpi = 0,
1171     .orientation_minimum = -1,
1172     .orientation_maximum = 2,
1173     .max_finger_cnt = 15,
1174     .max_touch_cnt = 5,
1175     .supports_t5r2 = 0,
1176     .support_semi_mt = 0,
1177     .is_button_pad = 0,
1178     .has_wheel = 0,
1179     .wheel_is_hi_res = 0,
1180     .is_haptic_pad = 0,
1181   };
1182   TestInterpreterWrapper wrapper(&interpreter, &initial_hwprops);
1183 
1184   CyapaQuickTwoFingerMoveTestInputs inputs[] = {
1185     { 1.13156, 38.16,  8.10, 52.2, 57.41,  6.40, 40.5, 75.66,  6.50, 36.7 },
1186     { 1.14369, 37.91, 17.50, 50.2, 56.83, 15.50, 40.5, 75.25, 15.30, 32.8 },
1187     { 1.15980, 34.66, 31.60, 48.3, 53.58, 29.40, 40.5, 72.25, 29.10, 28.9 }
1188   };
1189   // Prime it w/ a dummy hardware state
1190   stime_t timeout = NO_DEADLINE;
1191   HardwareState temp_hs = make_hwstate(0.000001, 0, 0, 0, nullptr);
1192   interpreter.SyncInterpret(temp_hs, &timeout);
1193 
1194   base_interpreter->expected_ids_.insert(1);
1195   base_interpreter->expected_ids_.insert(2);
1196   base_interpreter->expected_ids_.insert(3);
1197   for (size_t i = 0; i < arraysize(inputs); i++) {
1198     const CyapaQuickTwoFingerMoveTestInputs& input = inputs[i];
1199     FingerState fs[] = {
1200       { 0, 0, 0, 0, input.pressure0, 0, input.x0, input.y0, 1, 0 },
1201       { 0, 0, 0, 0, input.pressure1, 0, input.x1, input.y1, 2, 0 },
1202       { 0, 0, 0, 0, input.pressure2, 0, input.x2, input.y2, 3, 0 }
1203     };
1204     HardwareState hs =
1205         make_hwstate(input.now, 0, arraysize(fs), arraysize(fs), fs);
1206     timeout = NO_DEADLINE;
1207     interpreter.SyncInterpret(hs, &timeout);
1208     if (timeout >= 0) {
1209       stime_t next_timestamp = INFINITY;
1210       if (i < arraysize(inputs) - 1)
1211         next_timestamp = inputs[i + 1].now;
1212       stime_t now = input.now;
1213       while (timeout >= 0 && (now + timeout) < next_timestamp) {
1214         now += timeout;
1215         timeout = NO_DEADLINE;
1216         fprintf(stderr, "calling handler timer: %f\n", now);
1217         interpreter.HandleTimer(now, &timeout);
1218       }
1219     }
1220   }
1221 }
1222 
TEST(LookaheadFilterInterpreterTest,SemiMtNoTrackingIdAssignmentTest)1223 TEST(LookaheadFilterInterpreterTest, SemiMtNoTrackingIdAssignmentTest) {
1224   LookaheadFilterInterpreterTestInterpreter* base_interpreter = nullptr;
1225   std::unique_ptr<LookaheadFilterInterpreter> interpreter;
1226 
1227   HardwareProperties hwprops = {
1228     .right = 100, .bottom = 100,
1229     .res_x = 1,
1230     .res_y = 1,
1231     .screen_x_dpi = 0,
1232     .screen_y_dpi = 0,
1233     .orientation_minimum = -1,
1234     .orientation_maximum = 2,
1235     .max_finger_cnt = 2, .max_touch_cnt = 5,
1236     .supports_t5r2 = 1, .support_semi_mt = 1, .is_button_pad = 0,
1237     .has_wheel = 0, .wheel_is_hi_res = 0,
1238     .is_haptic_pad = 0,
1239   };
1240   TestInterpreterWrapper wrapper(interpreter.get(), &hwprops);
1241 
1242   FingerState fs[] = {
1243     // TM, Tm, WM, Wm, pr, orient, x, y, id
1244     { 0, 0, 0, 0, 5, 0, 76, 45, 20, 0},  // 0
1245 
1246     { 0, 0, 0, 0, 62, 0, 56, 43, 20, 0},  // 1
1247     { 0, 0, 0, 0, 62, 0, 76, 41, 21, 0},
1248 
1249     { 0, 0, 0, 0, 76, 0, 56, 38, 20, 0},  // 3
1250     { 0, 0, 0, 0, 76, 0, 75, 35, 21, 0},
1251 
1252     { 0, 0, 0, 0, 78, 0, 56, 31, 20, 0},  // 5
1253     { 0, 0, 0, 0, 78, 0, 75, 27, 21, 0},
1254 
1255     { 0, 0, 0, 0, 78, 0, 56, 22, 20, 0},  // 7
1256     { 0, 0, 0, 0, 78, 0, 75, 18, 21, 0},
1257 
1258     // It will trigger the tracking id assignment for a quick move on a
1259     // non-semi-mt device.
1260     { 0, 0, 0, 0, 78, 0, 56, 13, 20, 0},  // 9
1261     { 0, 0, 0, 0, 78, 0, 75, 8, 21, 0}
1262   };
1263 
1264   HardwareState hs[] = {
1265     make_hwstate(328.989039, 0, 1, 1, &fs[0]),
1266     make_hwstate(329.013853, 0, 2, 2, &fs[1]),
1267     make_hwstate(329.036266, 0, 2, 2, &fs[3]),
1268     make_hwstate(329.061772, 0, 2, 2, &fs[5]),
1269     make_hwstate(329.086734, 0, 2, 2, &fs[7]),
1270     make_hwstate(329.110350, 0, 2, 2, &fs[9]),
1271   };
1272 
1273   base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
1274   interpreter.reset(new LookaheadFilterInterpreter(
1275       nullptr, base_interpreter, nullptr));
1276   wrapper.Reset(interpreter.get());
1277 
1278   stime_t timeout = NO_DEADLINE;
1279   const auto& queue = interpreter->queue_;
1280 
1281   wrapper.SyncInterpret(hs[0], &timeout);
1282   EXPECT_EQ(queue.back().fs_[0].tracking_id, 20);
1283 
1284   // Test if the fingers in queue have the same tracking ids from input.
1285   for (size_t i = 1; i < arraysize(hs); i++) {
1286     wrapper.SyncInterpret(hs[i], &timeout);
1287     EXPECT_EQ(queue.back().fs_[0].tracking_id, 20);  // the same input id
1288     EXPECT_EQ(queue.back().fs_[1].tracking_id, 21);
1289   }
1290 }
1291 
TEST(LookaheadFilterInterpreterTest,AddFingerFlingTest)1292 TEST(LookaheadFilterInterpreterTest, AddFingerFlingTest) {
1293   LookaheadFilterInterpreterTestInterpreter* base_interpreter = nullptr;
1294   std::unique_ptr<LookaheadFilterInterpreter> interpreter;
1295 
1296   HardwareProperties hwprops = {
1297     .right = 100, .bottom = 100,
1298     .res_x = 1,
1299     .res_y = 1,
1300     .screen_x_dpi = 0,
1301     .screen_y_dpi = 0,
1302     .orientation_minimum = -1,
1303     .orientation_maximum = 2,
1304     .max_finger_cnt = 2, .max_touch_cnt = 5,
1305     .supports_t5r2 = 1, .support_semi_mt = 1, .is_button_pad = 0,
1306     .has_wheel = 0, .wheel_is_hi_res = 0,
1307     .is_haptic_pad = 0,
1308   };
1309   TestInterpreterWrapper wrapper(interpreter.get(), &hwprops);
1310 
1311   base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
1312   interpreter.reset(new LookaheadFilterInterpreter(
1313       nullptr, base_interpreter, nullptr));
1314   wrapper.Reset(interpreter.get());
1315 
1316   // Gesture Consumer that verifies and counts each Fling type gesture
1317   class FlingConsumer : public GestureConsumer {
1318     public:
1319       void ConsumeGesture(const Gesture& gesture) {
1320         EXPECT_EQ(gesture.type, kGestureTypeFling);
1321         ++gestures_consumed_;
1322       }
1323       int gestures_consumed_ = 0;
1324   } fling_consumer{};
1325   interpreter->consumer_ = &fling_consumer;
1326 
1327   FingerState fs[] = {
1328     // TM, Tm, WM, Wm, pr, orient, x, y, id
1329     { 0, 0, 0, 0, 5, 0, 76, 45, 20, 0},  // 0 - One Finger
1330 
1331     { 0, 0, 0, 0, 62, 0, 56, 43, 20, 0}, // 1 - Two Fingers
1332     { 0, 0, 0, 0, 62, 0, 76, 41, 21, 0},
1333   };
1334   HardwareState hs[] = {
1335     make_hwstate(328.989039, 0, 1, 1, &fs[0]),
1336     make_hwstate(329.013853, 0, 2, 2, &fs[1]),
1337   };
1338 
1339   // Disable Suppress Immediate Tapdown
1340   interpreter->suppress_immediate_tapdown_.val_ = 0;
1341 
1342   // Run through the two hardware states and verify a fling is detected
1343   stime_t timeout = NO_DEADLINE;
1344   EXPECT_EQ(fling_consumer.gestures_consumed_, 0);
1345   wrapper.SyncInterpret(hs[0], &timeout);
1346   EXPECT_EQ(fling_consumer.gestures_consumed_, 0);
1347   wrapper.SyncInterpret(hs[1], &timeout);
1348   EXPECT_EQ(fling_consumer.gestures_consumed_, 1);
1349 }
1350 
TEST(LookaheadFilterInterpreterTest,ConsumeGestureTest)1351 TEST(LookaheadFilterInterpreterTest, ConsumeGestureTest) {
1352   LookaheadFilterInterpreterTestInterpreter* base_interpreter = nullptr;
1353   std::unique_ptr<LookaheadFilterInterpreter> interpreter;
1354 
1355   HardwareProperties hwprops = {
1356     .right = 100, .bottom = 100,
1357     .res_x = 1,
1358     .res_y = 1,
1359     .screen_x_dpi = 0,
1360     .screen_y_dpi = 0,
1361     .orientation_minimum = -1,
1362     .orientation_maximum = 2,
1363     .max_finger_cnt = 2, .max_touch_cnt = 5,
1364     .supports_t5r2 = 1, .support_semi_mt = 1, .is_button_pad = 0,
1365     .has_wheel = 0, .wheel_is_hi_res = 0,
1366     .is_haptic_pad = 0,
1367   };
1368   TestInterpreterWrapper wrapper(interpreter.get(), &hwprops);
1369 
1370   base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
1371   interpreter.reset(new LookaheadFilterInterpreter(
1372       nullptr, base_interpreter, nullptr));
1373   wrapper.Reset(interpreter.get());
1374 
1375   // Gesture Consumer that counts each Metrics and Scroll type gesture
1376   class TestGestureConsumer : public GestureConsumer {
1377     public:
1378       void ConsumeGesture(const Gesture& gesture) {
1379         if (gesture.type == kGestureTypeMetrics)
1380           ++metric_gestures_consumed_;
1381         else if (gesture.type == kGestureTypeScroll)
1382           ++scroll_gestures_consumed_;
1383       }
1384       int metric_gestures_consumed_ = 0;
1385       int scroll_gestures_consumed_ = 0;
1386   } test_consumer{};
1387   interpreter->consumer_ = &test_consumer;
1388 
1389   // Both gestures counters should start with zero
1390   EXPECT_EQ(test_consumer.metric_gestures_consumed_, 0);
1391   EXPECT_EQ(test_consumer.scroll_gestures_consumed_, 0);
1392 
1393   // Push a Metrics gesture into the interpreter
1394   interpreter->ConsumeGesture(Gesture(kGestureMetrics, 0, 0,
1395                               kGestureMetricsTypeMouseMovement,
1396                               0, 0));
1397 
1398   // Verify it was detected
1399   EXPECT_EQ(test_consumer.metric_gestures_consumed_, 1);
1400   EXPECT_EQ(test_consumer.scroll_gestures_consumed_, 0);
1401 
1402   // Push a Scroll gesture into the interpreter
1403   interpreter->ConsumeGesture(Gesture(kGestureScroll, 0, 0, 0, 0));
1404 
1405   // Verify it was detected
1406   EXPECT_EQ(test_consumer.metric_gestures_consumed_, 1);
1407   EXPECT_EQ(test_consumer.scroll_gestures_consumed_, 1);
1408 }
1409 
1410 }  // namespace gestures
1411