• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 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 <gtest/gtest.h>
6 
7 #include "include/haptic_button_generator_filter_interpreter.h"
8 #include "include/unittest_util.h"
9 
10 namespace gestures {
11 
12 namespace {
13 class HapticButtonGeneratorFilterInterpreterTest : public ::testing::Test {};
14 
15 class HapticButtonGeneratorFilterInterpreterTestInterpreter :
16       public Interpreter {
17  public:
HapticButtonGeneratorFilterInterpreterTestInterpreter()18   HapticButtonGeneratorFilterInterpreterTestInterpreter()
19       : Interpreter(NULL, NULL, false) {}
SyncInterpret(HardwareState * hwstate,stime_t * timeout)20   virtual void SyncInterpret(HardwareState* hwstate, stime_t* timeout) {
21     if (return_value_.type != kGestureTypeNull)
22       ProduceGesture(return_value_);
23   }
24 
HandleTimer(stime_t now,stime_t * timeout)25   virtual void HandleTimer(stime_t now, stime_t* timeout) {
26     ADD_FAILURE() << "HandleTimer on the next interpreter shouldn't be called";
27   }
28 
29   Gesture return_value_;
30 };
31 
32 struct GestureTestInputs {
33   stime_t time;
34   short touch_count; // -1 for timer callback
35   FingerState* fs;
36   Gesture gesture;
37   stime_t expected_button;
38 };
39 
40 } // namespace {}
41 
TEST(HapticButtonGeneratorFilterInterpreterTest,SimpleTest)42 TEST(HapticButtonGeneratorFilterInterpreterTest, SimpleTest) {
43   HapticButtonGeneratorFilterInterpreterTestInterpreter* base_interpreter =
44       new HapticButtonGeneratorFilterInterpreterTestInterpreter;
45   HapticButtonGeneratorFilterInterpreter interpreter(
46       NULL, base_interpreter, NULL);
47   HardwareProperties hwprops = {
48     0, 0, 100, 100,  // left, top, right, bottom
49     10,  // x res (pixels/mm)
50     10,  // y res (pixels/mm)
51     133, 133,  // scrn DPI X, Y
52     -1,  // orientation minimum
53     2,   // orientation maximum
54     2, 5,  // max fingers, max_touch
55     0, 0, 0,  // t5r2, semi, button pad
56     0, 0,  // has wheel, vertical wheel is high resolution
57     1,  // haptic pad
58   };
59   TestInterpreterWrapper wrapper(&interpreter, &hwprops);
60 
61   interpreter.enabled_.val_ = true;
62 
63   FingerState fs[] = {
64     // TM, Tm, WM, Wm, pr, orient, x, y, id, flag
65     { 0, 0, 0, 0, 50, 0, 10, 1, 1, 0 },
66     { 0, 0, 0, 0, 50, 0, 10, 1, 1, 0 },
67     { 0, 0, 0, 0, 50, 0, 10, 1, 1, 0 },
68 
69     { 0, 0, 0, 0, 50, 0, 10, 1, 1, 0 },
70     { 0, 0, 0, 0, 120, 0, 10, 1, 1, 0 },
71     { 0, 0, 0, 0, 160, 0, 10, 1, 1, 0 },
72 
73     { 0, 0, 0, 0, 160, 0, 10, 1, 1, 0 },
74     { 0, 0, 0, 0, 120, 0, 10, 1, 1, 0 },
75     { 0, 0, 0, 0, 50, 0, 10, 1, 1, 0 },
76 
77     { 0, 0, 0, 0, 50, 0, 10, 1, 1, 0 },
78     { 0, 0, 0, 0, 50, 0, 10, 1, 2, 0 },
79     { 0, 0, 0, 0, 80, 0, 10, 1, 1, 0 },
80     { 0, 0, 0, 0, 80, 0, 10, 1, 2, 0 },
81 
82     { 0, 0, 0, 0, 160, 0, 10, 1, 1, 0 },
83     { 0, 0, 0, 0, 80, 0, 10, 1, 2, 0 },
84   };
85   HardwareState hs[] = {
86     // Expect to remove button press generated by firmare
87     make_hwstate(1.01, 0, 1, 1, &fs[0]),
88     make_hwstate(1.02, GESTURES_BUTTON_LEFT, 1, 1, &fs[1]),
89     make_hwstate(1.03, 0, 1, 1, &fs[2]),
90 
91     // Expect to set button down when going above 'down force threshold' (130)
92     make_hwstate(2.01, 0, 1, 1, &fs[3]),
93     make_hwstate(2.03, 0, 1, 1, &fs[4]),
94     make_hwstate(2.05, 0, 1, 1, &fs[5]),
95 
96     // Expect to set button up when going below 'up force threshold' (105)
97     make_hwstate(3.01, 0, 1, 1, &fs[6]),
98     make_hwstate(3.03, 0, 1, 1, &fs[7]),
99     make_hwstate(3.05, 0, 1, 1, &fs[8]),
100 
101     // Expect not to set button down when no individual finger goes above the
102     // 'down force threshold' (130), even if multiple combined do
103     make_hwstate(4.01, 0, 2, 2, &fs[9]),
104     make_hwstate(4.03, 0, 2, 2, &fs[11]),
105 
106     // Expect to set button down when one of multiple fingers goes above the
107     // 'down force threshold'
108     make_hwstate(4.05, 0, 2, 2, &fs[13]),
109 
110     // Expect to set button up after all fingers leave
111     make_hwstate(5.01, 0, 0, 0, NULL),
112   };
113 
114   stime_t expected_buttons[] = {
115     0, 0, 0,
116     0, 0, GESTURES_BUTTON_LEFT,
117     GESTURES_BUTTON_LEFT, GESTURES_BUTTON_LEFT, 0,
118     0, 0,
119     GESTURES_BUTTON_LEFT,
120     0
121   };
122 
123   for (size_t i = 0; i < arraysize(hs); i++) {
124     stime_t timeout = NO_DEADLINE;
125     wrapper.SyncInterpret(&hs[i], &timeout);
126     EXPECT_EQ(hs[i].buttons_down, expected_buttons[i]);
127   }
128 }
129 
TEST(HapticButtonGeneratorFilterInterpreterTest,NotHapticTest)130 TEST(HapticButtonGeneratorFilterInterpreterTest, NotHapticTest) {
131   HapticButtonGeneratorFilterInterpreterTestInterpreter* base_interpreter =
132       new HapticButtonGeneratorFilterInterpreterTestInterpreter;
133   HapticButtonGeneratorFilterInterpreter interpreter(
134       NULL, base_interpreter, NULL);
135   HardwareProperties hwprops = {
136     0, 0, 100, 100,  // left, top, right, bottom
137     10,  // x res (pixels/mm)
138     10,  // y res (pixels/mm)
139     133, 133,  // scrn DPI X, Y
140     -1,  // orientation minimum
141     2,   // orientation maximum
142     2, 5,  // max fingers, max_touch
143     0, 0, 0,  // t5r2, semi, button pad
144     0, 0,  // has wheel, vertical wheel is high resolution
145     0,  // haptic pad
146   };
147   TestInterpreterWrapper wrapper(&interpreter, &hwprops);
148 
149   interpreter.enabled_.val_ = true;
150 
151   FingerState fs[] = {
152     // TM, Tm, WM, Wm, pr, orient, x, y, id, flag
153     { 0, 0, 0, 0, 50, 0, 10, 1, 1, 0 },
154     { 0, 0, 0, 0, 50, 0, 10, 1, 1, 0 },
155     { 0, 0, 0, 0, 50, 0, 10, 1, 1, 0 },
156 
157     { 0, 0, 0, 0, 50, 0, 10, 1, 1, 0 },
158     { 0, 0, 0, 0, 120, 0, 10, 1, 1, 0 },
159     { 0, 0, 0, 0, 160, 0, 10, 1, 1, 0 },
160   };
161   HardwareState hs[] = {
162     // Expect to keep button press generated by firmware
163     make_hwstate(1.01, 0, 1, 1, &fs[0]),
164     make_hwstate(1.02, GESTURES_BUTTON_LEFT, 1, 1, &fs[1]),
165     make_hwstate(1.03, 0, 1, 1, &fs[2]),
166 
167     // Expect to not generate a button pres
168     make_hwstate(2.01, 0, 1, 1, &fs[3]),
169     make_hwstate(2.03, 0, 1, 1, &fs[4]),
170     make_hwstate(2.05, 0, 1, 1, &fs[5]),
171   };
172 
173   stime_t expected_buttons[] = {
174     0, GESTURES_BUTTON_LEFT, 0,
175     0, 0, 0
176   };
177 
178   for (size_t i = 0; i < arraysize(hs); i++) {
179     stime_t timeout = NO_DEADLINE;
180     wrapper.SyncInterpret(&hs[i], &timeout);
181     EXPECT_EQ(hs[i].buttons_down, expected_buttons[i]);
182   }
183 }
184 
TEST(HapticButtonGeneratorFilterInterpreterTest,GesturePreventsButtonDownTest)185 TEST(HapticButtonGeneratorFilterInterpreterTest,
186      GesturePreventsButtonDownTest) {
187   HapticButtonGeneratorFilterInterpreterTestInterpreter* base_interpreter =
188       new HapticButtonGeneratorFilterInterpreterTestInterpreter;
189   HapticButtonGeneratorFilterInterpreter interpreter(
190       NULL, base_interpreter, NULL);
191   HardwareProperties hwprops = {
192     0, 0, 100, 100,  // left, top, right, bottom
193     10,  // x res (pixels/mm)
194     10,  // y res (pixels/mm)
195     133, 133,  // scrn DPI X, Y
196     -1,  // orientation minimum
197     2,   // orientation maximum
198     2, 5,  // max fingers, max_touch
199     0, 0, 0,  // t5r2, semi, button pad
200     0, 0,  // has wheel, vertical wheel is high resolution
201     1,  // haptic pad
202   };
203   TestInterpreterWrapper wrapper(&interpreter, &hwprops);
204 
205   interpreter.enabled_.val_ = true;
206 
207   // TM, Tm, WM, Wm, pr, orient, x, y, id, flag
208   FingerState fs_low_force[] = {
209     { 0, 0, 0, 0, 50, 0, 10, 1, 1, 0 },
210     { 0, 0, 0, 0, 50, 0, 10, 1, 2, 0 },
211   };
212   FingerState fs_high_force[] = {
213     { 0, 0, 0, 0, 160, 0, 10, 1, 1, 0 },
214     { 0, 0, 0, 0, 160, 0, 10, 1, 2, 0 },
215   };
216 
217   const Gesture kNull = Gesture();
218   const Gesture kScroll = Gesture(kGestureScroll, 0, 0, 20, 0);
219   const Gesture kFling = Gesture(kGestureFling, 0, 0, 20, 0,
220                                  GESTURES_FLING_START);
221 
222   GestureTestInputs inputs[] = {
223     // Don't set the button down if a gesture is active.
224     {1.00, 2, fs_low_force,  kScroll, GESTURES_BUTTON_NONE},
225     {1.01, 2, fs_high_force, kFling,  GESTURES_BUTTON_NONE},
226 
227     // If the button is down before a gesture starts, don't prevent the button
228     // from going back up.
229     {2.000, 2, fs_low_force,  kNull,   GESTURES_BUTTON_NONE},
230     {2.010, 2, fs_high_force, kNull,   GESTURES_BUTTON_LEFT},
231     {2.030, 2, fs_high_force, kScroll, GESTURES_BUTTON_LEFT},
232     {2.040, 2, fs_low_force,  kScroll, GESTURES_BUTTON_NONE},
233     {2.050, 2, fs_low_force,  kFling,  GESTURES_BUTTON_NONE},
234 
235     // If there is no "ending" gesture event, allow button clicks after a short
236     // timeout.
237     {3.000, 2, fs_low_force,  kScroll, GESTURES_BUTTON_NONE},
238     {3.010, 2, fs_high_force, kNull,   GESTURES_BUTTON_NONE},
239     {3.011, 2, fs_high_force, kNull,   GESTURES_BUTTON_NONE},
240     {3.011 + interpreter.active_gesture_timeout_, -1, NULL, kNull, 0},
241     {3.200 + interpreter.active_gesture_timeout_,
242             2, fs_high_force, kNull,   GESTURES_BUTTON_LEFT},
243   };
244 
245   for (size_t i = 0; i < arraysize(inputs); i++) {
246     GestureTestInputs input = inputs[i];
247     base_interpreter->return_value_ = input.gesture;
248     stime_t timeout = NO_DEADLINE;
249     if (input.touch_count == -1) {
250       wrapper.HandleTimer(input.time, &timeout);
251     } else {
252       unsigned short touch_count =
253           static_cast<unsigned short>(input.touch_count);
254       HardwareState hs = make_hwstate(input.time, 0, touch_count, touch_count,
255                                       input.fs);
256       wrapper.SyncInterpret(&hs, &timeout);
257       EXPECT_EQ(hs.buttons_down, input.expected_button);
258     }
259   }
260 }
261 
TEST(HapticButtonGeneratorFilterInterpreterTest,DynamicThresholdTest)262 TEST(HapticButtonGeneratorFilterInterpreterTest, DynamicThresholdTest) {
263   HapticButtonGeneratorFilterInterpreterTestInterpreter* base_interpreter =
264       new HapticButtonGeneratorFilterInterpreterTestInterpreter;
265   HapticButtonGeneratorFilterInterpreter interpreter(
266       NULL, base_interpreter, NULL);
267   HardwareProperties hwprops = {
268     0, 0, 100, 100,  // left, top, right, bottom
269     10,  // x res (pixels/mm)
270     10,  // y res (pixels/mm)
271     133, 133,  // scrn DPI X, Y
272     -1,  // orientation minimum
273     2,   // orientation maximum
274     2, 5,  // max fingers, max_touch
275     0, 0, 0,  // t5r2, semi, button pad
276     0, 0,  // has wheel, vertical wheel is high resolution
277     1,  // haptic pad
278   };
279   TestInterpreterWrapper wrapper(&interpreter, &hwprops);
280 
281   interpreter.enabled_.val_ = true;
282   interpreter.use_dynamic_thresholds_.val_ = true;
283 
284   FingerState fs[] = {
285     // TM, Tm, WM, Wm, pr, orient, x, y, id, flag
286     { 0, 0, 0, 0, 50, 0, 10, 1, 1, 0 },
287     { 0, 0, 0, 0, 120, 0, 10, 1, 1, 0 },
288     { 0, 0, 0, 0, 160, 0, 10, 1, 1, 0 },
289 
290     { 0, 0, 0, 0, 500, 0, 10, 1, 1, 0 },
291     { 0, 0, 0, 0, 300, 0, 10, 1, 1, 0 },
292     { 0, 0, 0, 0, 200, 0, 10, 1, 1, 0 },
293 
294     { 0, 0, 0, 0, 220, 0, 10, 1, 1, 0 },
295     { 0, 0, 0, 0, 250, 0, 10, 1, 1, 0 },
296 
297     { 0, 0, 0, 0, 10, 0, 10, 1, 1, 0 },
298     { 0, 0, 0, 0, 120, 0, 10, 1, 1, 0 },
299     { 0, 0, 0, 0, 140, 0, 10, 1, 1, 0 },
300 
301     { 0, 0, 0, 0, 110, 0, 10, 1, 1, 0 },
302     { 0, 0, 0, 0, 100, 0, 10, 1, 1, 0 },
303   };
304 
305   std::pair<HardwareState, int> hs[] = {
306     // Expect to set button down when going above 'down force threshold' (130)
307     std::make_pair(make_hwstate(1.01, 0, 1, 1, &fs[0]), 0),
308     std::make_pair(make_hwstate(1.03, 0, 1, 1, &fs[1]), 0),
309     std::make_pair(make_hwstate(1.05, 0, 1, 1, &fs[2]), GESTURES_BUTTON_LEFT),
310 
311     // Expect to increase button up threshold after seeing a very high force.
312     // Default 'up force threshold' is 105, but it increases to half of the max
313     // force seen.
314     std::make_pair(make_hwstate(2.01, 0, 1, 1, &fs[3]), GESTURES_BUTTON_LEFT),
315     std::make_pair(make_hwstate(2.03, 0, 1, 1, &fs[4]), GESTURES_BUTTON_LEFT),
316     std::make_pair(make_hwstate(2.05, 0, 1, 1, &fs[5]), 0),
317 
318     // Expect to increase 'button down threshold' after seeing a very high
319     // force.
320     std::make_pair(make_hwstate(3.01, 0, 1, 1, &fs[6]), 0),
321     std::make_pair(make_hwstate(3.03, 0, 1, 1, &fs[7]), GESTURES_BUTTON_LEFT),
322 
323     // Expect 'button down threshold' to return to normal (130) after seeing a
324     // low pressure value.
325     std::make_pair(make_hwstate(4.01, 0, 1, 1, &fs[8]), 0),
326     std::make_pair(make_hwstate(4.03, 0, 1, 1, &fs[9]), 0),
327     std::make_pair(make_hwstate(4.05, 0, 1, 1, &fs[10]), GESTURES_BUTTON_LEFT),
328 
329     // Expect 'button up threshold' to return to normal after seeing a low
330     // pressure value.
331     std::make_pair(make_hwstate(5.01, 0, 1, 1, &fs[11]), GESTURES_BUTTON_LEFT),
332     std::make_pair(make_hwstate(5.03, 0, 1, 1, &fs[12]), 0),
333   };
334 
335   for (size_t i = 0; i < arraysize(hs); i++) {
336     stime_t timeout = NO_DEADLINE;
337     wrapper.SyncInterpret(&hs[i].first, &timeout);
338     EXPECT_EQ(hs[i].first.buttons_down, hs[i].second);
339   }
340 }
341 
TEST(HapticButtonGeneratorFilterInterpreterTest,PalmTest)342 TEST(HapticButtonGeneratorFilterInterpreterTest, PalmTest) {
343   HapticButtonGeneratorFilterInterpreterTestInterpreter* base_interpreter =
344       new HapticButtonGeneratorFilterInterpreterTestInterpreter;
345   HapticButtonGeneratorFilterInterpreter interpreter(
346       NULL, base_interpreter, NULL);
347   HardwareProperties hwprops = {
348     0, 0, 100, 100,  // left, top, right, bottom
349     10,  // x res (pixels/mm)
350     10,  // y res (pixels/mm)
351     133, 133,  // scrn DPI X, Y
352     -1,  // orientation minimum
353     2,   // orientation maximum
354     2, 5,  // max fingers, max_touch
355     0, 0, 0,  // t5r2, semi, button pad
356     0, 0,  // has wheel, vertical wheel is high resolution
357     1,  // haptic pad
358   };
359   TestInterpreterWrapper wrapper(&interpreter, &hwprops);
360 
361   interpreter.enabled_.val_ = true;
362 
363   FingerState fs[] = {
364     // TM, Tm, WM, Wm, pr, orient, x, y, id, flag
365     { 0, 0, 0, 0, 50, 0, 10, 1, 1, GESTURES_FINGER_LARGE_PALM },
366     { 0, 0, 0, 0, 160, 0, 10, 1, 1, GESTURES_FINGER_LARGE_PALM },
367     { 0, 0, 0, 0, 50, 0, 10, 1, 1, GESTURES_FINGER_LARGE_PALM },
368 
369     { 0, 0, 0, 0, 50, 0, 10, 1, 1, GESTURES_FINGER_LARGE_PALM },
370     { 0, 0, 0, 0, 50, 0, 10, 1, 2, 0 },
371     { 0, 0, 0, 0, 160, 0, 10, 1, 1, GESTURES_FINGER_LARGE_PALM },
372     { 0, 0, 0, 0, 80, 0, 10, 1, 2, 0 },
373 
374     { 0, 0, 0, 0, 160, 0, 10, 1, 1, GESTURES_FINGER_LARGE_PALM },
375     { 0, 0, 0, 0, 160, 0, 10, 1, 2, 0 },
376   };
377   HardwareState hs[] = {
378     // Expect not to set button down when a lone palm goes above 'down force
379     // threshold'
380     make_hwstate(2.01, 0, 1, 1, &fs[0]),
381     make_hwstate(2.03, 0, 1, 1, &fs[1]),
382     make_hwstate(2.05, 0, 1, 1, &fs[2]),
383 
384     // Expect not to set button down when there are multiple fingers and only a
385     // palm goes above 'down force threshold'
386     make_hwstate(4.01, 0, 2, 2, &fs[3]),
387     make_hwstate(4.03, 0, 2, 2, &fs[5]),
388 
389     // Expect to set button down when there are multiple fingers and a non-palm
390     // goes above 'down force threshold'
391     make_hwstate(4.05, 0, 2, 2, &fs[7]),
392   };
393 
394   stime_t expected_buttons[] = {
395     0, 0, 0,
396     0, 0,
397     GESTURES_BUTTON_LEFT,
398   };
399 
400   for (size_t i = 0; i < arraysize(hs); i++) {
401     stime_t timeout = NO_DEADLINE;
402     wrapper.SyncInterpret(&hs[i], &timeout);
403     EXPECT_EQ(hs[i].buttons_down, expected_buttons[i]);
404   }
405 }
406 
407 }  // namespace gestures
408