1 // Copyright 2012 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <deque>
6 #include <math.h>
7 #include <vector>
8 #include <utility>
9
10 #include <gtest/gtest.h>
11
12 #include "include/gestures.h"
13 #include "include/sensor_jump_filter_interpreter.h"
14 #include "include/unittest_util.h"
15
16 using std::deque;
17 using std::make_pair;
18 using std::pair;
19 using std::vector;
20
21 namespace gestures {
22
23 class SensorJumpFilterInterpreterTest : public ::testing::Test {};
24
25 class SensorJumpFilterInterpreterTestInterpreter : public Interpreter {
26 public:
SensorJumpFilterInterpreterTestInterpreter()27 SensorJumpFilterInterpreterTestInterpreter()
28 : Interpreter(nullptr, nullptr, false),
29 handle_timer_called_(false),
30 expected_finger_cnt_(-1) {}
31
SyncInterpret(HardwareState & hwstate,stime_t * timeout)32 virtual void SyncInterpret(HardwareState& hwstate, stime_t* timeout) {
33 if (expected_finger_cnt_ >= 0) {
34 EXPECT_EQ(1, hwstate.finger_cnt);
35 prev_ = hwstate.fingers[0];
36 }
37 }
38
HandleTimer(stime_t now,stime_t * timeout)39 virtual void HandleTimer(stime_t now, stime_t* timeout) {
40 handle_timer_called_ = true;
41 }
42
43 FingerState prev_;
44 bool handle_timer_called_;
45 short expected_finger_cnt_;
46 };
47
48 struct InputAndExpectedWarp {
49 float val;
50 bool warp;
51 };
52
TEST(SensorJumpFilterInterpreterTest,SimpleTest)53 TEST(SensorJumpFilterInterpreterTest, SimpleTest) {
54 SensorJumpFilterInterpreterTestInterpreter* base_interpreter =
55 new SensorJumpFilterInterpreterTestInterpreter;
56 SensorJumpFilterInterpreter interpreter(nullptr, base_interpreter, nullptr);
57
58 base_interpreter->expected_finger_cnt_ = 1;
59 interpreter.enabled_.val_ = 1;
60
61 HardwareProperties hwprops = {
62 .right = 100, .bottom = 100,
63 .res_x = 1, .res_y = 1,
64 .orientation_minimum = -1,
65 .orientation_maximum = 2,
66 .max_finger_cnt = 5, .max_touch_cnt = 5,
67 .supports_t5r2 = 0, .support_semi_mt = 0, .is_button_pad = 1,
68 .has_wheel = 0, .wheel_is_hi_res = 0,
69 .is_haptic_pad = 0,
70 };
71 TestInterpreterWrapper wrapper(&interpreter, &hwprops);
72
73 EXPECT_FALSE(base_interpreter->handle_timer_called_);
74 wrapper.HandleTimer(0.0, nullptr);
75 EXPECT_TRUE(base_interpreter->handle_timer_called_);
76
77 FingerState fs = { 0, 0, 0, 0, 1, 0, 3.0, 0.0, 1, 0 };
78 HardwareState hs = make_hwstate(0.0, 0, 1, 1, &fs);
79
80 InputAndExpectedWarp data[] = {
81 { 3.0, false },
82 { 4.0, false },
83 { 3.0, true }, // switch direction
84 { 4.0, true }, // switch direction
85 { 5.0, true }, // prev was flagged
86 { 6.0, false },
87 { 6.1, false },
88 { 7.1, true }, // suspicious
89 { 17.1, false }, // very large--okay
90 };
91
92 stime_t now = 0.0;
93 const stime_t kTimeDelta = 0.01;
94 for (size_t i = 0; i < arraysize(data); i++) {
95 now += kTimeDelta;
96 hs.timestamp = now;
97 fs.flags = 0;
98 fs.position_y = data[i].val;
99 wrapper.SyncInterpret(hs, nullptr);
100 const unsigned kFlags = GESTURES_FINGER_WARP_Y |
101 GESTURES_FINGER_WARP_Y_TAP_MOVE |
102 GESTURES_FINGER_WARP_TELEPORTATION;
103 EXPECT_EQ(data[i].warp ? kFlags : 0, fs.flags) << "i=" << i;
104 }
105 }
106
107 struct ActualLogInputs {
108 stime_t timestamp;
109 float x0, y0, p0;
110 short id0;
111 float x1, y1, p1;
112 short id1;
113 };
114
115 // Real log with jumping fingers. Should only scroll in one direction
TEST(SensorJumpFilterInterpreterTest,ActualLogTest)116 TEST(SensorJumpFilterInterpreterTest, ActualLogTest) {
117 SensorJumpFilterInterpreterTestInterpreter* base_interpreter =
118 new SensorJumpFilterInterpreterTestInterpreter;
119 SensorJumpFilterInterpreter interpreter(nullptr, base_interpreter, nullptr);
120
121 interpreter.enabled_.val_ = 1;
122
123 HardwareProperties hwprops = {
124 .right = 106.666672, .bottom = 68,
125 .res_x = 1, .res_y = 1,
126 .orientation_minimum = -1,
127 .orientation_maximum = 2,
128 .max_finger_cnt = 15, .max_touch_cnt = 5,
129 .supports_t5r2 = 0, .support_semi_mt = 0, .is_button_pad = 1,
130 .has_wheel = 0, .wheel_is_hi_res = 0,
131 .is_haptic_pad = 0,
132 };
133 TestInterpreterWrapper wrapper(&interpreter, &hwprops);
134
135 ActualLogInputs inputs[] = {
136 { 19.554, 56.666, 59.400, 118.201, 6, 35.083, 58.200, 118.201, 7 },
137 { 19.566, 56.583, 59.299, 118.201, 6, 35.083, 58.100, 118.201, 7 },
138 { 19.578, 56.583, 59.100, 118.201, 6, 35.000, 58.100, 118.201, 7 },
139 { 19.590, 56.500, 58.900, 118.201, 6, 34.750, 55.100, 116.261, 7 },
140 { 19.601, 56.416, 58.799, 118.201, 6, 34.666, 54.900, 118.201, 7 },
141 { 19.613, 56.333, 58.700, 118.201, 6, 34.666, 54.600, 118.201, 7 },
142 { 19.625, 56.250, 58.500, 118.201, 6, 34.583, 54.500, 118.201, 7 },
143 { 19.637, 56.166, 58.400, 118.201, 6, 34.583, 54.200, 118.201, 7 },
144 { 19.648, 56.166, 58.299, 118.201, 6, 34.416, 53.900, 118.201, 7 },
145 { 19.660, 56.083, 58.100, 118.201, 6, 34.416, 53.700, 118.201, 7 },
146 { 19.672, 56.083, 58.100, 118.201, 6, 34.333, 53.500, 118.201, 7 },
147 { 19.684, 56.083, 58.000, 118.201, 6, 34.250, 53.400, 118.201, 7 },
148 { 19.696, 56.000, 57.900, 118.201, 6, 34.166, 53.200, 118.201, 7 },
149 { 19.708, 55.916, 57.799, 118.201, 6, 34.166, 53.100, 118.201, 7 },
150 { 19.720, 55.916, 57.799, 118.201, 6, 34.166, 53.000, 118.201, 7 },
151 { 19.732, 55.916, 57.799, 118.201, 6, 34.083, 52.799, 118.201, 7 },
152 { 19.744, 55.916, 57.799, 118.201, 6, 34.083, 52.700, 118.201, 7 },
153 { 19.756, 55.833, 57.700, 118.201, 6, 34.000, 52.600, 118.201, 7 },
154 { 19.768, 55.833, 57.500, 118.201, 6, 34.000, 52.500, 118.201, 7 },
155 { 19.779, 55.333, 56.000, 118.201, 6, 34.000, 52.700, 118.201, 7 },
156 { 19.791, 55.333, 55.900, 118.201, 6, 34.000, 52.700, 118.201, 7 },
157 { 19.801, 55.333, 55.799, 118.201, 6, 34.000, 52.600, 118.201, 7 },
158 { 19.813, 55.333, 55.400, 118.201, 6, 33.833, 52.200, 118.201, 7 },
159 { 19.824, 55.333, 55.299, 118.201, 6, 33.833, 52.000, 118.201, 7 },
160 { 19.835, 55.333, 55.200, 118.201, 6, 33.833, 51.799, 118.201, 7 },
161 { 19.846, 55.333, 55.000, 118.201, 6, 33.750, 51.500, 118.201, 7 },
162 { 19.857, 55.333, 54.700, 118.201, 6, 33.750, 51.200, 118.201, 7 },
163 { 19.868, 55.333, 54.500, 118.201, 6, 33.750, 50.600, 118.201, 7 },
164 { 19.880, 55.250, 54.299, 118.201, 6, 33.666, 50.500, 118.201, 7 },
165 { 19.891, 55.250, 54.299, 118.201, 6, 33.666, 50.299, 118.201, 7 },
166 { 19.902, 55.166, 54.100, 118.201, 6, 33.666, 50.100, 118.201, 7 },
167 { 19.913, 55.166, 53.900, 116.261, 6, 33.666, 49.900, 118.201, 7 },
168 { 19.924, 55.083, 53.900, 116.261, 6, 33.666, 49.799, 118.201, 7 },
169 { 19.935, 55.083, 53.700, 116.261, 6, 33.583, 49.500, 118.201, 7 },
170 { 19.947, 55.083, 53.500, 112.380, 6, 33.583, 49.299, 118.201, 7 },
171 { 19.958, 55.083, 53.299, 110.439, 6, 33.583, 49.100, 118.201, 7 },
172 { 19.969, 55.083, 53.100, 106.559, 6, 33.500, 48.900, 118.201, 7 },
173 { 19.980, 55.000, 52.900, 104.618, 6, 33.416, 48.799, 118.201, 7 },
174 { 19.991, 55.000, 52.799, 102.678, 6, 33.416, 48.600, 118.201, 7 },
175 { 20.002, 55.000, 52.600, 98.7977, 6, 33.416, 48.299, 118.201, 7 },
176 { 20.013, 54.916, 52.500, 96.8573, 6, 33.416, 48.000, 118.201, 7 },
177 { 20.025, 54.833, 52.299, 92.9766, 6, 33.416, 47.700, 118.201, 7 },
178 { 20.036, 54.666, 50.299, 118.201, 6, 33.333, 47.400, 118.201, 7 },
179 { 20.047, 54.666, 50.100, 118.201, 6, 33.250, 47.000, 118.201, 7 },
180 { 20.058, 54.666, 49.700, 118.201, 6, 33.250, 46.799, 118.201, 7 },
181 { 20.069, 54.500, 49.299, 118.201, 6, 33.166, 46.299, 118.201, 7 },
182 { 20.080, 54.416, 49.000, 118.201, 6, 33.166, 46.100, 118.201, 7 },
183 { 20.091, 54.416, 48.700, 118.201, 6, 33.083, 45.600, 118.201, 7 },
184 { 20.102, 54.416, 48.600, 118.201, 6, 33.083, 45.299, 118.201, 7 },
185 { 20.113, 54.416, 48.299, 118.201, 6, 33.000, 45.000, 118.201, 7 },
186 { 20.124, 54.416, 48.100, 118.201, 6, 33.000, 44.700, 118.201, 7 },
187 { 20.135, 54.333, 47.700, 118.201, 6, 32.916, 44.000, 118.201, 7 },
188 { 20.147, 54.250, 47.500, 118.201, 6, 32.833, 43.600, 118.201, 7 },
189 { 20.158, 54.250, 47.400, 114.320, 6, 32.833, 43.400, 118.201, 7 },
190 { 20.169, 54.250, 47.200, 112.380, 6, 32.750, 43.100, 118.201, 7 },
191 { 20.180, 54.250, 47.000, 108.499, 6, 32.750, 42.799, 118.201, 7 },
192 { 20.191, 54.250, 46.799, 106.559, 6, 32.666, 42.600, 118.201, 7 },
193 { 20.202, 54.250, 46.600, 102.678, 6, 32.583, 42.299, 118.201, 7 },
194 { 20.213, 54.166, 46.400, 98.7977, 6, 32.583, 42.000, 118.201, 7 },
195 { 20.224, 54.000, 44.400, 118.201, 6, 32.583, 41.700, 118.201, 7 },
196 { 20.235, 53.916, 44.000, 118.201, 6, 32.416, 41.200, 118.201, 7 },
197 { 20.246, 53.833, 43.600, 118.201, 6, 32.416, 40.900, 118.201, 7 },
198 { 20.257, 53.833, 43.299, 118.201, 6, 32.416, 40.500, 118.201, 7 },
199 { 20.268, 53.750, 43.000, 118.201, 6, 32.416, 40.200, 118.201, 7 },
200 { 20.280, 53.750, 42.799, 118.201, 6, 32.333, 40.000, 118.201, 7 },
201 { 20.291, 53.750, 42.500, 118.201, 6, 32.333, 39.600, 118.201, 7 },
202 { 20.302, 53.750, 42.400, 118.201, 6, 32.250, 39.200, 118.201, 7 },
203 { 20.313, 53.666, 42.200, 118.201, 6, 32.166, 38.299, 118.201, 7 },
204 { 20.324, 53.666, 41.900, 118.201, 6, 32.166, 38.000, 118.201, 7 },
205 { 20.335, 53.666, 41.900, 118.201, 6, 32.166, 37.900, 118.201, 7 },
206 { 20.347, 53.583, 41.500, 118.201, 6, 32.166, 37.700, 118.201, 7 },
207 { 20.360, 53.500, 40.700, 182.233, 6, 31.666, 35.100, 118.201, 7 },
208 { 20.374, 53.416, 40.200, 182.233, 6, 31.666, 35.000, 118.201, 7 },
209 { 20.388, 53.416, 40.000, 182.233, 6, 31.666, 39.100, 118.201, 7 },
210 { 20.401, 53.416, 39.700, 184.173, 6, 31.666, 38.900, 118.201, 7 },
211 { 20.415, 53.333, 39.299, 184.173, 6, 31.666, 38.900, 118.201, 7 },
212 { 20.429, 53.333, 38.900, 182.233, 6, 31.583, 38.700, 118.201, 7 },
213 { 20.441, 52.666, 35.200, 118.201, 6, 31.666, 38.600, 118.201, 7 },
214 { 20.453, 52.750, 35.100, 118.201, 6, 31.583, 38.500, 118.201, 7 },
215 { 20.466, 52.666, 34.900, 118.201, 6, 31.666, 35.299, 189.995, 7 },
216 { 20.480, 52.666, 34.799, 118.201, 6, 31.666, 35.000, 193.875, 7 },
217 { 20.494, 52.666, 34.600, 118.201, 6, 31.666, 34.500, 191.935, 7 },
218 { 20.507, 52.583, 34.500, 118.201, 6, 31.666, 34.299, 193.875, 7 },
219 { 20.519, 52.583, 34.400, 118.201, 6, 31.333, 37.799, 118.201, 7 },
220 { 20.533, 52.583, 34.299, 118.201, 6, 31.583, 33.700, 195.816, 7 },
221 { 20.545, 52.666, 34.100, 118.201, 6, 31.000, 29.700, 118.201, 7 },
222 { 20.557, 52.583, 34.000, 118.201, 6, 31.000, 29.400, 118.201, 7 },
223 { 20.569, 52.583, 34.000, 118.201, 6, 31.000, 29.200, 118.201, 7 },
224 { 20.581, 52.583, 34.000, 118.201, 6, 31.000, 29.100, 118.201, 7 },
225 { 20.593, 52.583, 33.799, 118.201, 6, 30.916, 28.900, 118.201, 7 },
226 { 20.605, 52.583, 33.799, 118.201, 6, 30.916, 28.800, 118.201, 7 },
227 };
228
229 FingerState fs[] = {
230 { 0, 0, 0, 0, 1, 0, 3.0, 0.0, 1, 0 },
231 { 0, 0, 0, 0, 1, 0, 3.0, 0.0, 1, 0 },
232 };
233 HardwareState hs = make_hwstate(0.0, 0, 2, 2, &fs[0]);
234
235 float prev_y_out[] = { 0.0, 0.0 };
236
237 for (size_t i = 0; i < arraysize(inputs); i++) {
238 const ActualLogInputs& input = inputs[i];
239 hs.timestamp = input.timestamp;
240 fs[0].position_x = input.x0;
241 fs[0].position_y = input.y0;
242 fs[0].pressure = input.p0;
243 fs[0].tracking_id = input.id0;
244 fs[1].position_x = input.x1;
245 fs[1].position_y = input.y1;
246 fs[1].pressure = input.p1;
247 fs[1].tracking_id = input.id1;
248 wrapper.SyncInterpret(hs, nullptr);
249 if (i != 0) { // can't do deltas with the first input
250 float dy[] = { fs[0].position_y - prev_y_out[0],
251 fs[1].position_y - prev_y_out[1] };
252 for (size_t j = 0; j < arraysize(dy); j++) {
253 if (fs[j].flags & GESTURES_FINGER_WARP_Y)
254 dy[j] = 0.0;
255 EXPECT_LE(dy[j], 0.0) << "i=" << i << " j=" << j;
256 }
257 }
258 prev_y_out[0] = fs[0].position_y;
259 prev_y_out[1] = fs[1].position_y;
260 }
261 }
262
263 } // namespace gestures
264