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