xref: /aosp_15_r20/external/libchrome-gestures/src/gestures.cc (revision aed3e5085e770be5b69ce25295ecf6ddf906af95)
1*aed3e508SAndroid Build Coastguard Worker // Copyright 2012 The ChromiumOS Authors
2*aed3e508SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*aed3e508SAndroid Build Coastguard Worker // found in the LICENSE file.
4*aed3e508SAndroid Build Coastguard Worker 
5*aed3e508SAndroid Build Coastguard Worker #include "include/gestures.h"
6*aed3e508SAndroid Build Coastguard Worker 
7*aed3e508SAndroid Build Coastguard Worker #include <cstring>
8*aed3e508SAndroid Build Coastguard Worker #include <sys/time.h>
9*aed3e508SAndroid Build Coastguard Worker 
10*aed3e508SAndroid Build Coastguard Worker #include "include/accel_filter_interpreter.h"
11*aed3e508SAndroid Build Coastguard Worker #include "include/box_filter_interpreter.h"
12*aed3e508SAndroid Build Coastguard Worker #include "include/click_wiggle_filter_interpreter.h"
13*aed3e508SAndroid Build Coastguard Worker #include "include/finger_merge_filter_interpreter.h"
14*aed3e508SAndroid Build Coastguard Worker #include "include/finger_metrics.h"
15*aed3e508SAndroid Build Coastguard Worker #include "include/fling_stop_filter_interpreter.h"
16*aed3e508SAndroid Build Coastguard Worker #include "include/haptic_button_generator_filter_interpreter.h"
17*aed3e508SAndroid Build Coastguard Worker #include "include/iir_filter_interpreter.h"
18*aed3e508SAndroid Build Coastguard Worker #include "include/immediate_interpreter.h"
19*aed3e508SAndroid Build Coastguard Worker #include "include/integral_gesture_filter_interpreter.h"
20*aed3e508SAndroid Build Coastguard Worker #include "include/logging.h"
21*aed3e508SAndroid Build Coastguard Worker #include "include/logging_filter_interpreter.h"
22*aed3e508SAndroid Build Coastguard Worker #include "include/lookahead_filter_interpreter.h"
23*aed3e508SAndroid Build Coastguard Worker #include "include/metrics_filter_interpreter.h"
24*aed3e508SAndroid Build Coastguard Worker #include "include/mouse_interpreter.h"
25*aed3e508SAndroid Build Coastguard Worker #include "include/multitouch_mouse_interpreter.h"
26*aed3e508SAndroid Build Coastguard Worker #include "include/non_linearity_filter_interpreter.h"
27*aed3e508SAndroid Build Coastguard Worker #include "include/palm_classifying_filter_interpreter.h"
28*aed3e508SAndroid Build Coastguard Worker #include "include/prop_registry.h"
29*aed3e508SAndroid Build Coastguard Worker #include "include/scaling_filter_interpreter.h"
30*aed3e508SAndroid Build Coastguard Worker #include "include/sensor_jump_filter_interpreter.h"
31*aed3e508SAndroid Build Coastguard Worker #include "include/split_correcting_filter_interpreter.h"
32*aed3e508SAndroid Build Coastguard Worker #include "include/stationary_wiggle_filter_interpreter.h"
33*aed3e508SAndroid Build Coastguard Worker #include "include/string_util.h"
34*aed3e508SAndroid Build Coastguard Worker #include "include/stuck_button_inhibitor_filter_interpreter.h"
35*aed3e508SAndroid Build Coastguard Worker #include "include/t5r2_correcting_filter_interpreter.h"
36*aed3e508SAndroid Build Coastguard Worker #include "include/timestamp_filter_interpreter.h"
37*aed3e508SAndroid Build Coastguard Worker #include "include/trace_marker.h"
38*aed3e508SAndroid Build Coastguard Worker #include "include/tracer.h"
39*aed3e508SAndroid Build Coastguard Worker #include "include/trend_classifying_filter_interpreter.h"
40*aed3e508SAndroid Build Coastguard Worker #include "include/util.h"
41*aed3e508SAndroid Build Coastguard Worker 
42*aed3e508SAndroid Build Coastguard Worker using std::string;
43*aed3e508SAndroid Build Coastguard Worker using std::min;
44*aed3e508SAndroid Build Coastguard Worker using gestures::StringPrintf;
45*aed3e508SAndroid Build Coastguard Worker 
46*aed3e508SAndroid Build Coastguard Worker // C API:
47*aed3e508SAndroid Build Coastguard Worker 
48*aed3e508SAndroid Build Coastguard Worker static const int kMinSupportedVersion = 1;
49*aed3e508SAndroid Build Coastguard Worker static const int kMaxSupportedVersion = 1;
50*aed3e508SAndroid Build Coastguard Worker 
StimeFromTimeval(const struct timeval * tv)51*aed3e508SAndroid Build Coastguard Worker stime_t StimeFromTimeval(const struct timeval* tv) {
52*aed3e508SAndroid Build Coastguard Worker   return static_cast<stime_t>(tv->tv_sec) +
53*aed3e508SAndroid Build Coastguard Worker       static_cast<stime_t>(tv->tv_usec) / 1000000.0;
54*aed3e508SAndroid Build Coastguard Worker }
55*aed3e508SAndroid Build Coastguard Worker 
StimeFromTimespec(const struct timespec * ts)56*aed3e508SAndroid Build Coastguard Worker stime_t StimeFromTimespec(const struct timespec* ts) {
57*aed3e508SAndroid Build Coastguard Worker   return static_cast<stime_t>(ts->tv_sec) +
58*aed3e508SAndroid Build Coastguard Worker       static_cast<stime_t>(ts->tv_nsec) / 1000000000.0;
59*aed3e508SAndroid Build Coastguard Worker }
60*aed3e508SAndroid Build Coastguard Worker 
String() const61*aed3e508SAndroid Build Coastguard Worker std::string HardwareProperties::String() const {
62*aed3e508SAndroid Build Coastguard Worker   return StringPrintf("%f,  // left edge\n"
63*aed3e508SAndroid Build Coastguard Worker                       "%f,  // top edge\n"
64*aed3e508SAndroid Build Coastguard Worker                       "%f,  // right edge\n"
65*aed3e508SAndroid Build Coastguard Worker                       "%f,  // bottom edge\n"
66*aed3e508SAndroid Build Coastguard Worker                       "%f,  // x pixels/TP width\n"
67*aed3e508SAndroid Build Coastguard Worker                       "%f,  // y pixels/TP height\n"
68*aed3e508SAndroid Build Coastguard Worker                       "%f,  // orientation minimum\n"
69*aed3e508SAndroid Build Coastguard Worker                       "%f,  // orientation maximum\n"
70*aed3e508SAndroid Build Coastguard Worker                       "%u,  // max fingers\n"
71*aed3e508SAndroid Build Coastguard Worker                       "%u,  // max touch\n"
72*aed3e508SAndroid Build Coastguard Worker                       "%u,  // t5r2\n"
73*aed3e508SAndroid Build Coastguard Worker                       "%u,  // semi-mt\n"
74*aed3e508SAndroid Build Coastguard Worker                       "%u   // is button pad\n",
75*aed3e508SAndroid Build Coastguard Worker                       left, top, right, bottom,
76*aed3e508SAndroid Build Coastguard Worker                       res_x,
77*aed3e508SAndroid Build Coastguard Worker                       res_y,
78*aed3e508SAndroid Build Coastguard Worker                       orientation_minimum,
79*aed3e508SAndroid Build Coastguard Worker                       orientation_maximum,
80*aed3e508SAndroid Build Coastguard Worker                       max_finger_cnt,
81*aed3e508SAndroid Build Coastguard Worker                       max_touch_cnt,
82*aed3e508SAndroid Build Coastguard Worker                       supports_t5r2,
83*aed3e508SAndroid Build Coastguard Worker                       support_semi_mt,
84*aed3e508SAndroid Build Coastguard Worker                       is_button_pad);
85*aed3e508SAndroid Build Coastguard Worker }
86*aed3e508SAndroid Build Coastguard Worker 
87*aed3e508SAndroid Build Coastguard Worker namespace {
NameForFingerStateFlag(unsigned flag)88*aed3e508SAndroid Build Coastguard Worker string NameForFingerStateFlag(unsigned flag) {
89*aed3e508SAndroid Build Coastguard Worker #define CASERET(name)                           \
90*aed3e508SAndroid Build Coastguard Worker   case GESTURES_FINGER_##name: return #name
91*aed3e508SAndroid Build Coastguard Worker   switch (flag) {
92*aed3e508SAndroid Build Coastguard Worker     CASERET(WARP_X_NON_MOVE);
93*aed3e508SAndroid Build Coastguard Worker     CASERET(WARP_Y_NON_MOVE);
94*aed3e508SAndroid Build Coastguard Worker     CASERET(NO_TAP);
95*aed3e508SAndroid Build Coastguard Worker     CASERET(POSSIBLE_PALM);
96*aed3e508SAndroid Build Coastguard Worker     CASERET(PALM);
97*aed3e508SAndroid Build Coastguard Worker     CASERET(WARP_X_MOVE);
98*aed3e508SAndroid Build Coastguard Worker     CASERET(WARP_Y_MOVE);
99*aed3e508SAndroid Build Coastguard Worker     CASERET(WARP_X_TAP_MOVE);
100*aed3e508SAndroid Build Coastguard Worker     CASERET(WARP_Y_TAP_MOVE);
101*aed3e508SAndroid Build Coastguard Worker     CASERET(MERGE);
102*aed3e508SAndroid Build Coastguard Worker     CASERET(TREND_INC_X);
103*aed3e508SAndroid Build Coastguard Worker     CASERET(TREND_DEC_X);
104*aed3e508SAndroid Build Coastguard Worker     CASERET(TREND_INC_Y);
105*aed3e508SAndroid Build Coastguard Worker     CASERET(TREND_DEC_Y);
106*aed3e508SAndroid Build Coastguard Worker     CASERET(TREND_INC_PRESSURE);
107*aed3e508SAndroid Build Coastguard Worker     CASERET(TREND_DEC_PRESSURE);
108*aed3e508SAndroid Build Coastguard Worker     CASERET(TREND_INC_TOUCH_MAJOR);
109*aed3e508SAndroid Build Coastguard Worker     CASERET(TREND_DEC_TOUCH_MAJOR);
110*aed3e508SAndroid Build Coastguard Worker     CASERET(INSTANTANEOUS_MOVING);
111*aed3e508SAndroid Build Coastguard Worker     CASERET(WARP_TELEPORTATION);
112*aed3e508SAndroid Build Coastguard Worker   }
113*aed3e508SAndroid Build Coastguard Worker #undef CASERET
114*aed3e508SAndroid Build Coastguard Worker   return "";
115*aed3e508SAndroid Build Coastguard Worker }
116*aed3e508SAndroid Build Coastguard Worker }  // namespace {}
117*aed3e508SAndroid Build Coastguard Worker 
FlagsString(unsigned flags)118*aed3e508SAndroid Build Coastguard Worker string FingerState::FlagsString(unsigned flags) {
119*aed3e508SAndroid Build Coastguard Worker   string ret;
120*aed3e508SAndroid Build Coastguard Worker   const char kPipeSeparator[] = " | ";
121*aed3e508SAndroid Build Coastguard Worker   for (unsigned i = 0; i < 8 * sizeof(flags); i++) {
122*aed3e508SAndroid Build Coastguard Worker     const unsigned flag = 1 << i;
123*aed3e508SAndroid Build Coastguard Worker     const string name = NameForFingerStateFlag(flag);
124*aed3e508SAndroid Build Coastguard Worker     if ((flags & flag) && !name.empty()) {
125*aed3e508SAndroid Build Coastguard Worker       ret += kPipeSeparator;
126*aed3e508SAndroid Build Coastguard Worker       ret += name;
127*aed3e508SAndroid Build Coastguard Worker       flags &= ~flag;
128*aed3e508SAndroid Build Coastguard Worker     }
129*aed3e508SAndroid Build Coastguard Worker   }
130*aed3e508SAndroid Build Coastguard Worker   if (flags) {
131*aed3e508SAndroid Build Coastguard Worker     // prepend remaining number
132*aed3e508SAndroid Build Coastguard Worker     ret = StringPrintf("%u%s", flags, ret.c_str());
133*aed3e508SAndroid Build Coastguard Worker   } else if (ret.rfind(kPipeSeparator, 0) == 0) {
134*aed3e508SAndroid Build Coastguard Worker     // strip extra pipe
135*aed3e508SAndroid Build Coastguard Worker     ret = ret.substr(strlen(kPipeSeparator));
136*aed3e508SAndroid Build Coastguard Worker   } else {
137*aed3e508SAndroid Build Coastguard Worker     ret = "no flags";
138*aed3e508SAndroid Build Coastguard Worker   }
139*aed3e508SAndroid Build Coastguard Worker   return ret;
140*aed3e508SAndroid Build Coastguard Worker }
141*aed3e508SAndroid Build Coastguard Worker 
String() const142*aed3e508SAndroid Build Coastguard Worker string FingerState::String() const {
143*aed3e508SAndroid Build Coastguard Worker   return StringPrintf("{ %d: (%.2f, %.2f), touch %.2fx%.2f, width %.2fx%.2f, "
144*aed3e508SAndroid Build Coastguard Worker                       "pressure %.2f, orient %.2f%s }",
145*aed3e508SAndroid Build Coastguard Worker                       tracking_id,
146*aed3e508SAndroid Build Coastguard Worker                       position_x, position_y,
147*aed3e508SAndroid Build Coastguard Worker                       touch_major, touch_minor,
148*aed3e508SAndroid Build Coastguard Worker                       width_major, width_minor,
149*aed3e508SAndroid Build Coastguard Worker                       pressure,
150*aed3e508SAndroid Build Coastguard Worker                       orientation,
151*aed3e508SAndroid Build Coastguard Worker                       flags ? (", " + FlagsString(flags)).c_str() : "");
152*aed3e508SAndroid Build Coastguard Worker }
153*aed3e508SAndroid Build Coastguard Worker 
GetFingerState(short tracking_id)154*aed3e508SAndroid Build Coastguard Worker FingerState* HardwareState::GetFingerState(short tracking_id) {
155*aed3e508SAndroid Build Coastguard Worker   return const_cast<FingerState*>(
156*aed3e508SAndroid Build Coastguard Worker       const_cast<const HardwareState*>(this)->GetFingerState(tracking_id));
157*aed3e508SAndroid Build Coastguard Worker }
158*aed3e508SAndroid Build Coastguard Worker 
GetFingerState(short tracking_id) const159*aed3e508SAndroid Build Coastguard Worker const FingerState* HardwareState::GetFingerState(short tracking_id) const {
160*aed3e508SAndroid Build Coastguard Worker   for (short i = 0; i < finger_cnt; i++) {
161*aed3e508SAndroid Build Coastguard Worker     if (fingers[i].tracking_id == tracking_id)
162*aed3e508SAndroid Build Coastguard Worker       return &fingers[i];
163*aed3e508SAndroid Build Coastguard Worker   }
164*aed3e508SAndroid Build Coastguard Worker   return nullptr;
165*aed3e508SAndroid Build Coastguard Worker }
166*aed3e508SAndroid Build Coastguard Worker 
String() const167*aed3e508SAndroid Build Coastguard Worker string HardwareState::String() const {
168*aed3e508SAndroid Build Coastguard Worker   string ret = StringPrintf("{ %f, buttons 0x%x, %d f, %d t, {",
169*aed3e508SAndroid Build Coastguard Worker                             timestamp,
170*aed3e508SAndroid Build Coastguard Worker                             buttons_down,
171*aed3e508SAndroid Build Coastguard Worker                             finger_cnt,
172*aed3e508SAndroid Build Coastguard Worker                             touch_cnt);
173*aed3e508SAndroid Build Coastguard Worker   for (size_t i = 0; i < finger_cnt; i++) {
174*aed3e508SAndroid Build Coastguard Worker     if (i != 0)
175*aed3e508SAndroid Build Coastguard Worker       ret += ",";
176*aed3e508SAndroid Build Coastguard Worker     ret += " ";
177*aed3e508SAndroid Build Coastguard Worker     ret += fingers[i].String();
178*aed3e508SAndroid Build Coastguard Worker   }
179*aed3e508SAndroid Build Coastguard Worker   if (finger_cnt > 0)
180*aed3e508SAndroid Build Coastguard Worker     ret += " ";
181*aed3e508SAndroid Build Coastguard Worker   ret += "} }";
182*aed3e508SAndroid Build Coastguard Worker   return ret;
183*aed3e508SAndroid Build Coastguard Worker }
184*aed3e508SAndroid Build Coastguard Worker 
SameFingersAs(const HardwareState & that) const185*aed3e508SAndroid Build Coastguard Worker bool HardwareState::SameFingersAs(const HardwareState& that) const {
186*aed3e508SAndroid Build Coastguard Worker   if (finger_cnt != that.finger_cnt || touch_cnt != that.touch_cnt)
187*aed3e508SAndroid Build Coastguard Worker     return false;
188*aed3e508SAndroid Build Coastguard Worker   // For now, require fingers to be in the same slots
189*aed3e508SAndroid Build Coastguard Worker   for (size_t i = 0; i < finger_cnt; i++)
190*aed3e508SAndroid Build Coastguard Worker     if (fingers[i].tracking_id != that.fingers[i].tracking_id)
191*aed3e508SAndroid Build Coastguard Worker       return false;
192*aed3e508SAndroid Build Coastguard Worker   return true;
193*aed3e508SAndroid Build Coastguard Worker }
194*aed3e508SAndroid Build Coastguard Worker 
DeepCopy(const HardwareState & that,unsigned short max_finger_cnt)195*aed3e508SAndroid Build Coastguard Worker void HardwareState::DeepCopy(const HardwareState& that,
196*aed3e508SAndroid Build Coastguard Worker                              unsigned short max_finger_cnt) {
197*aed3e508SAndroid Build Coastguard Worker   timestamp = that.timestamp;
198*aed3e508SAndroid Build Coastguard Worker   buttons_down = that.buttons_down;
199*aed3e508SAndroid Build Coastguard Worker   touch_cnt = that.touch_cnt;
200*aed3e508SAndroid Build Coastguard Worker   finger_cnt = min(that.finger_cnt, max_finger_cnt);
201*aed3e508SAndroid Build Coastguard Worker   if(that.fingers != nullptr) {
202*aed3e508SAndroid Build Coastguard Worker     memcpy(fingers, that.fingers, finger_cnt * sizeof(FingerState));
203*aed3e508SAndroid Build Coastguard Worker   } else if (finger_cnt > 0) {
204*aed3e508SAndroid Build Coastguard Worker     Err("HardwareState with no finger data but %d finger count", finger_cnt);
205*aed3e508SAndroid Build Coastguard Worker   }
206*aed3e508SAndroid Build Coastguard Worker   rel_x = that.rel_x;
207*aed3e508SAndroid Build Coastguard Worker   rel_y = that.rel_y;
208*aed3e508SAndroid Build Coastguard Worker   rel_wheel = that.rel_wheel;
209*aed3e508SAndroid Build Coastguard Worker   rel_wheel_hi_res = that.rel_wheel_hi_res;
210*aed3e508SAndroid Build Coastguard Worker   rel_hwheel = that.rel_hwheel;
211*aed3e508SAndroid Build Coastguard Worker   msc_timestamp = that.msc_timestamp;
212*aed3e508SAndroid Build Coastguard Worker }
213*aed3e508SAndroid Build Coastguard Worker 
String() const214*aed3e508SAndroid Build Coastguard Worker string Gesture::String() const {
215*aed3e508SAndroid Build Coastguard Worker   switch (type) {
216*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeNull:
217*aed3e508SAndroid Build Coastguard Worker       return "(Gesture type: null)";
218*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeContactInitiated:
219*aed3e508SAndroid Build Coastguard Worker       return StringPrintf("(Gesture type: contactInitiated "
220*aed3e508SAndroid Build Coastguard Worker                           "start: %f stop: %f)", start_time, end_time);
221*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeMove:
222*aed3e508SAndroid Build Coastguard Worker       return StringPrintf("(Gesture type: move start: %f stop: %f "
223*aed3e508SAndroid Build Coastguard Worker                           "dx: %f dy: %f ordinal_dx: %f ordinal_dy: %f)",
224*aed3e508SAndroid Build Coastguard Worker                           start_time, end_time,
225*aed3e508SAndroid Build Coastguard Worker                           details.move.dx, details.move.dy,
226*aed3e508SAndroid Build Coastguard Worker                           details.move.ordinal_dx, details.move.ordinal_dy);
227*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeScroll:
228*aed3e508SAndroid Build Coastguard Worker       return StringPrintf("(Gesture type: scroll start: %f stop: %f "
229*aed3e508SAndroid Build Coastguard Worker                           "dx: %f dy: %f ordinal_dx: %f ordinal_dy: %f)",
230*aed3e508SAndroid Build Coastguard Worker                           start_time, end_time,
231*aed3e508SAndroid Build Coastguard Worker                           details.scroll.dx, details.scroll.dy,
232*aed3e508SAndroid Build Coastguard Worker                           details.scroll.ordinal_dx, details.scroll.ordinal_dy);
233*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeMouseWheel:
234*aed3e508SAndroid Build Coastguard Worker       return StringPrintf("(Gesture type: wheel start: %f stop %f "
235*aed3e508SAndroid Build Coastguard Worker                           "dx: %f dy: %f "
236*aed3e508SAndroid Build Coastguard Worker                           "tick_120ths_dx: %d tick_120ths_dy: %d)",
237*aed3e508SAndroid Build Coastguard Worker                           start_time, end_time,
238*aed3e508SAndroid Build Coastguard Worker                           details.wheel.dx, details.wheel.dy,
239*aed3e508SAndroid Build Coastguard Worker                           details.wheel.tick_120ths_dx,
240*aed3e508SAndroid Build Coastguard Worker                           details.wheel.tick_120ths_dy);
241*aed3e508SAndroid Build Coastguard Worker     case kGestureTypePinch:
242*aed3e508SAndroid Build Coastguard Worker       return StringPrintf("(Gesture type: pinch start: %f stop: %f "
243*aed3e508SAndroid Build Coastguard Worker                           "dz: %f ordinal_dz: %f, state: %d)", start_time,
244*aed3e508SAndroid Build Coastguard Worker                           end_time, details.pinch.dz, details.pinch.ordinal_dz,
245*aed3e508SAndroid Build Coastguard Worker                           details.pinch.zoom_state);
246*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeButtonsChange:
247*aed3e508SAndroid Build Coastguard Worker       return StringPrintf("(Gesture type: buttons start: %f stop: "
248*aed3e508SAndroid Build Coastguard Worker                           "%f down: %d up: %d is_tap: %s)", start_time, end_time,
249*aed3e508SAndroid Build Coastguard Worker                           details.buttons.down, details.buttons.up,
250*aed3e508SAndroid Build Coastguard Worker                           details.buttons.is_tap ? "true" : "false");
251*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeFling:
252*aed3e508SAndroid Build Coastguard Worker       return StringPrintf("(Gesture type: fling start: %f stop: "
253*aed3e508SAndroid Build Coastguard Worker                           "%f vx: %f vy: %f ordinal_dx: %f ordinal_dy: %f "
254*aed3e508SAndroid Build Coastguard Worker                           "state: %s)", start_time, end_time,
255*aed3e508SAndroid Build Coastguard Worker                           details.fling.vx, details.fling.vy,
256*aed3e508SAndroid Build Coastguard Worker                           details.fling.ordinal_vx, details.fling.ordinal_vy,
257*aed3e508SAndroid Build Coastguard Worker                           details.fling.fling_state == GESTURES_FLING_START ?
258*aed3e508SAndroid Build Coastguard Worker                           "start" : "tapdown");
259*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeSwipe:
260*aed3e508SAndroid Build Coastguard Worker       return StringPrintf("(Gesture type: swipe start: %f stop: %f "
261*aed3e508SAndroid Build Coastguard Worker                           "dx: %f dy: %f ordinal_dx: %f ordinal_dy: %f)",
262*aed3e508SAndroid Build Coastguard Worker                           start_time, end_time,
263*aed3e508SAndroid Build Coastguard Worker                           details.swipe.dx, details.swipe.dy,
264*aed3e508SAndroid Build Coastguard Worker                           details.swipe.ordinal_dx, details.swipe.ordinal_dy);
265*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeSwipeLift:
266*aed3e508SAndroid Build Coastguard Worker       return StringPrintf("(Gesture type: swipeLift start: %f stop: %f)",
267*aed3e508SAndroid Build Coastguard Worker                           start_time, end_time);
268*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeFourFingerSwipe:
269*aed3e508SAndroid Build Coastguard Worker       return StringPrintf("(Gesture type: fourFingerSwipe start: %f stop: %f "
270*aed3e508SAndroid Build Coastguard Worker                           "dx: %f dy: %f ordinal_dx: %f ordinal_dy: %f)",
271*aed3e508SAndroid Build Coastguard Worker                           start_time, end_time,
272*aed3e508SAndroid Build Coastguard Worker                           details.four_finger_swipe.dx,
273*aed3e508SAndroid Build Coastguard Worker                           details.four_finger_swipe.dy,
274*aed3e508SAndroid Build Coastguard Worker                           details.four_finger_swipe.ordinal_dx,
275*aed3e508SAndroid Build Coastguard Worker                           details.four_finger_swipe.ordinal_dy);
276*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeFourFingerSwipeLift:
277*aed3e508SAndroid Build Coastguard Worker       return StringPrintf("(Gesture type: fourFingerSwipeLift start: %f "
278*aed3e508SAndroid Build Coastguard Worker                           "stop: %f)", start_time, end_time);
279*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeMetrics:
280*aed3e508SAndroid Build Coastguard Worker       return StringPrintf("(Gesture type: metrics start: %f stop: %f "
281*aed3e508SAndroid Build Coastguard Worker                           "type: %d d1: %f d2: %f)", start_time, end_time,
282*aed3e508SAndroid Build Coastguard Worker                           details.metrics.type,
283*aed3e508SAndroid Build Coastguard Worker                           details.metrics.data[0], details.metrics.data[1]);
284*aed3e508SAndroid Build Coastguard Worker   }
285*aed3e508SAndroid Build Coastguard Worker   return "(Gesture type: unknown)";
286*aed3e508SAndroid Build Coastguard Worker }
287*aed3e508SAndroid Build Coastguard Worker 
operator ==(const Gesture & that) const288*aed3e508SAndroid Build Coastguard Worker bool Gesture::operator==(const Gesture& that) const {
289*aed3e508SAndroid Build Coastguard Worker   if (type != that.type)
290*aed3e508SAndroid Build Coastguard Worker     return false;
291*aed3e508SAndroid Build Coastguard Worker   bool times_equal = gestures::DoubleEq(start_time, that.start_time) &&
292*aed3e508SAndroid Build Coastguard Worker                      gestures::DoubleEq(end_time, that.end_time);
293*aed3e508SAndroid Build Coastguard Worker   switch (type) {
294*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeNull:  // fall through
295*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeContactInitiated:
296*aed3e508SAndroid Build Coastguard Worker       return true;
297*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeMove:
298*aed3e508SAndroid Build Coastguard Worker       return times_equal &&
299*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.move.dx, that.details.move.dx) &&
300*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.move.dy, that.details.move.dy);
301*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeScroll:
302*aed3e508SAndroid Build Coastguard Worker       return times_equal &&
303*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.scroll.dx, that.details.scroll.dx) &&
304*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.scroll.dy, that.details.scroll.dy);
305*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeMouseWheel:
306*aed3e508SAndroid Build Coastguard Worker       return times_equal &&
307*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.wheel.dx, that.details.wheel.dx) &&
308*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.wheel.dy, that.details.wheel.dy) &&
309*aed3e508SAndroid Build Coastguard Worker           details.wheel.tick_120ths_dx == that.details.wheel.tick_120ths_dx &&
310*aed3e508SAndroid Build Coastguard Worker           details.wheel.tick_120ths_dy == that.details.wheel.tick_120ths_dy;
311*aed3e508SAndroid Build Coastguard Worker     case kGestureTypePinch:
312*aed3e508SAndroid Build Coastguard Worker       return times_equal &&
313*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.pinch.dz, that.details.pinch.dz);
314*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeButtonsChange:
315*aed3e508SAndroid Build Coastguard Worker       return times_equal &&
316*aed3e508SAndroid Build Coastguard Worker           details.buttons.down == that.details.buttons.down &&
317*aed3e508SAndroid Build Coastguard Worker           details.buttons.up == that.details.buttons.up;
318*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeFling:
319*aed3e508SAndroid Build Coastguard Worker       return times_equal &&
320*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.fling.vx, that.details.fling.vx) &&
321*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.fling.vy, that.details.fling.vy);
322*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeSwipe:
323*aed3e508SAndroid Build Coastguard Worker       return times_equal &&
324*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.swipe.dx, that.details.swipe.dx);
325*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeSwipeLift:
326*aed3e508SAndroid Build Coastguard Worker       return times_equal;
327*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeFourFingerSwipe:
328*aed3e508SAndroid Build Coastguard Worker       return times_equal &&
329*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.four_finger_swipe.dx,
330*aed3e508SAndroid Build Coastguard Worker               that.details.four_finger_swipe.dx);
331*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeFourFingerSwipeLift:
332*aed3e508SAndroid Build Coastguard Worker       return times_equal;
333*aed3e508SAndroid Build Coastguard Worker     case kGestureTypeMetrics:
334*aed3e508SAndroid Build Coastguard Worker       return times_equal &&
335*aed3e508SAndroid Build Coastguard Worker           details.metrics.type == that.details.metrics.type &&
336*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.metrics.data[0],
337*aed3e508SAndroid Build Coastguard Worker               that.details.metrics.data[0]) &&
338*aed3e508SAndroid Build Coastguard Worker           gestures::FloatEq(details.metrics.data[1],
339*aed3e508SAndroid Build Coastguard Worker               that.details.metrics.data[1]);
340*aed3e508SAndroid Build Coastguard Worker   }
341*aed3e508SAndroid Build Coastguard Worker   return true;
342*aed3e508SAndroid Build Coastguard Worker }
343*aed3e508SAndroid Build Coastguard Worker 
NewGestureInterpreterImpl(int version)344*aed3e508SAndroid Build Coastguard Worker GestureInterpreter* NewGestureInterpreterImpl(int version) {
345*aed3e508SAndroid Build Coastguard Worker   if (version < kMinSupportedVersion) {
346*aed3e508SAndroid Build Coastguard Worker     Err("Client too old. It's using version %d"
347*aed3e508SAndroid Build Coastguard Worker         ", but library has min supported version %d",
348*aed3e508SAndroid Build Coastguard Worker         version,
349*aed3e508SAndroid Build Coastguard Worker         kMinSupportedVersion);
350*aed3e508SAndroid Build Coastguard Worker     return nullptr;
351*aed3e508SAndroid Build Coastguard Worker   }
352*aed3e508SAndroid Build Coastguard Worker   if (version > kMaxSupportedVersion) {
353*aed3e508SAndroid Build Coastguard Worker     Err("Client too new. It's using version %d"
354*aed3e508SAndroid Build Coastguard Worker         ", but library has max supported version %d",
355*aed3e508SAndroid Build Coastguard Worker         version,
356*aed3e508SAndroid Build Coastguard Worker         kMaxSupportedVersion);
357*aed3e508SAndroid Build Coastguard Worker     return nullptr;
358*aed3e508SAndroid Build Coastguard Worker   }
359*aed3e508SAndroid Build Coastguard Worker   return new gestures::GestureInterpreter(version);
360*aed3e508SAndroid Build Coastguard Worker }
361*aed3e508SAndroid Build Coastguard Worker 
DeleteGestureInterpreter(GestureInterpreter * obj)362*aed3e508SAndroid Build Coastguard Worker void DeleteGestureInterpreter(GestureInterpreter* obj) {
363*aed3e508SAndroid Build Coastguard Worker   delete obj;
364*aed3e508SAndroid Build Coastguard Worker }
365*aed3e508SAndroid Build Coastguard Worker 
GestureInterpreterPushHardwareState(GestureInterpreter * obj,struct HardwareState * hwstate)366*aed3e508SAndroid Build Coastguard Worker void GestureInterpreterPushHardwareState(GestureInterpreter* obj,
367*aed3e508SAndroid Build Coastguard Worker                                          struct HardwareState* hwstate) {
368*aed3e508SAndroid Build Coastguard Worker   obj->PushHardwareState(hwstate);
369*aed3e508SAndroid Build Coastguard Worker }
370*aed3e508SAndroid Build Coastguard Worker 
GestureInterpreterSetHardwareProperties(GestureInterpreter * obj,const struct HardwareProperties * hwprops)371*aed3e508SAndroid Build Coastguard Worker void GestureInterpreterSetHardwareProperties(
372*aed3e508SAndroid Build Coastguard Worker     GestureInterpreter* obj,
373*aed3e508SAndroid Build Coastguard Worker     const struct HardwareProperties* hwprops) {
374*aed3e508SAndroid Build Coastguard Worker   obj->SetHardwareProperties(*hwprops);
375*aed3e508SAndroid Build Coastguard Worker }
376*aed3e508SAndroid Build Coastguard Worker 
GestureInterpreterSetCallback(GestureInterpreter * obj,GestureReadyFunction fn,void * user_data)377*aed3e508SAndroid Build Coastguard Worker void GestureInterpreterSetCallback(GestureInterpreter* obj,
378*aed3e508SAndroid Build Coastguard Worker                                    GestureReadyFunction fn,
379*aed3e508SAndroid Build Coastguard Worker                                    void* user_data) {
380*aed3e508SAndroid Build Coastguard Worker   obj->SetCallback(fn, user_data);
381*aed3e508SAndroid Build Coastguard Worker }
382*aed3e508SAndroid Build Coastguard Worker 
GestureInterpreterSetTimerProvider(GestureInterpreter * obj,GesturesTimerProvider * tp,void * data)383*aed3e508SAndroid Build Coastguard Worker void GestureInterpreterSetTimerProvider(GestureInterpreter* obj,
384*aed3e508SAndroid Build Coastguard Worker                                         GesturesTimerProvider* tp,
385*aed3e508SAndroid Build Coastguard Worker                                         void* data) {
386*aed3e508SAndroid Build Coastguard Worker   obj->SetTimerProvider(tp, data);
387*aed3e508SAndroid Build Coastguard Worker }
388*aed3e508SAndroid Build Coastguard Worker 
GestureInterpreterSetPropProvider(GestureInterpreter * obj,GesturesPropProvider * pp,void * data)389*aed3e508SAndroid Build Coastguard Worker void GestureInterpreterSetPropProvider(GestureInterpreter* obj,
390*aed3e508SAndroid Build Coastguard Worker                                        GesturesPropProvider* pp,
391*aed3e508SAndroid Build Coastguard Worker                                        void* data) {
392*aed3e508SAndroid Build Coastguard Worker   obj->SetPropProvider(pp, data);
393*aed3e508SAndroid Build Coastguard Worker }
394*aed3e508SAndroid Build Coastguard Worker 
GestureInterpreterInitialize(GestureInterpreter * obj,enum GestureInterpreterDeviceClass cls)395*aed3e508SAndroid Build Coastguard Worker void GestureInterpreterInitialize(GestureInterpreter* obj,
396*aed3e508SAndroid Build Coastguard Worker                                   enum GestureInterpreterDeviceClass cls) {
397*aed3e508SAndroid Build Coastguard Worker   obj->Initialize(cls);
398*aed3e508SAndroid Build Coastguard Worker }
399*aed3e508SAndroid Build Coastguard Worker 
400*aed3e508SAndroid Build Coastguard Worker // C++ API:
401*aed3e508SAndroid Build Coastguard Worker namespace gestures {
402*aed3e508SAndroid Build Coastguard Worker class GestureInterpreterConsumer : public GestureConsumer {
403*aed3e508SAndroid Build Coastguard Worker  public:
GestureInterpreterConsumer(GestureReadyFunction callback,void * callback_data)404*aed3e508SAndroid Build Coastguard Worker   GestureInterpreterConsumer(GestureReadyFunction callback,
405*aed3e508SAndroid Build Coastguard Worker                              void* callback_data)
406*aed3e508SAndroid Build Coastguard Worker       : callback_(callback),
407*aed3e508SAndroid Build Coastguard Worker         callback_data_(callback_data) {}
408*aed3e508SAndroid Build Coastguard Worker 
SetCallback(GestureReadyFunction callback,void * callback_data)409*aed3e508SAndroid Build Coastguard Worker   void SetCallback(GestureReadyFunction callback, void* callback_data) {
410*aed3e508SAndroid Build Coastguard Worker     callback_ = callback;
411*aed3e508SAndroid Build Coastguard Worker     callback_data_ = callback_data;
412*aed3e508SAndroid Build Coastguard Worker   }
413*aed3e508SAndroid Build Coastguard Worker 
ConsumeGesture(const Gesture & gesture)414*aed3e508SAndroid Build Coastguard Worker   void ConsumeGesture(const Gesture& gesture) {
415*aed3e508SAndroid Build Coastguard Worker     AssertWithReturn(gesture.type != kGestureTypeNull);
416*aed3e508SAndroid Build Coastguard Worker     if (callback_)
417*aed3e508SAndroid Build Coastguard Worker       callback_(callback_data_, &gesture);
418*aed3e508SAndroid Build Coastguard Worker   }
419*aed3e508SAndroid Build Coastguard Worker 
420*aed3e508SAndroid Build Coastguard Worker  private:
421*aed3e508SAndroid Build Coastguard Worker   GestureReadyFunction callback_;
422*aed3e508SAndroid Build Coastguard Worker   void* callback_data_;
423*aed3e508SAndroid Build Coastguard Worker };
424*aed3e508SAndroid Build Coastguard Worker }
425*aed3e508SAndroid Build Coastguard Worker 
GestureInterpreter(int version)426*aed3e508SAndroid Build Coastguard Worker GestureInterpreter::GestureInterpreter(int version)
427*aed3e508SAndroid Build Coastguard Worker     : callback_(nullptr),
428*aed3e508SAndroid Build Coastguard Worker       callback_data_(nullptr),
429*aed3e508SAndroid Build Coastguard Worker       timer_provider_(nullptr),
430*aed3e508SAndroid Build Coastguard Worker       timer_provider_data_(nullptr),
431*aed3e508SAndroid Build Coastguard Worker       interpret_timer_(nullptr),
432*aed3e508SAndroid Build Coastguard Worker       loggingFilter_(nullptr) {
433*aed3e508SAndroid Build Coastguard Worker   prop_reg_.reset(new PropRegistry);
434*aed3e508SAndroid Build Coastguard Worker   tracer_.reset(new Tracer(prop_reg_.get(), TraceMarker::StaticTraceWrite));
435*aed3e508SAndroid Build Coastguard Worker   TraceMarker::CreateTraceMarker();
436*aed3e508SAndroid Build Coastguard Worker }
437*aed3e508SAndroid Build Coastguard Worker 
~GestureInterpreter()438*aed3e508SAndroid Build Coastguard Worker GestureInterpreter::~GestureInterpreter() {
439*aed3e508SAndroid Build Coastguard Worker   SetTimerProvider(nullptr, nullptr);
440*aed3e508SAndroid Build Coastguard Worker   SetPropProvider(nullptr, nullptr);
441*aed3e508SAndroid Build Coastguard Worker   TraceMarker::DeleteTraceMarker();
442*aed3e508SAndroid Build Coastguard Worker }
443*aed3e508SAndroid Build Coastguard Worker 
444*aed3e508SAndroid Build Coastguard Worker namespace {
InternalTimerCallback(stime_t now,void * callback_data)445*aed3e508SAndroid Build Coastguard Worker stime_t InternalTimerCallback(stime_t now, void* callback_data) {
446*aed3e508SAndroid Build Coastguard Worker   Log("TimerCallback called");
447*aed3e508SAndroid Build Coastguard Worker   GestureInterpreter* gi = reinterpret_cast<GestureInterpreter*>(callback_data);
448*aed3e508SAndroid Build Coastguard Worker   stime_t next = NO_DEADLINE;
449*aed3e508SAndroid Build Coastguard Worker   gi->TimerCallback(now, &next);
450*aed3e508SAndroid Build Coastguard Worker   return next;
451*aed3e508SAndroid Build Coastguard Worker }
452*aed3e508SAndroid Build Coastguard Worker }
453*aed3e508SAndroid Build Coastguard Worker 
PushHardwareState(HardwareState * hwstate)454*aed3e508SAndroid Build Coastguard Worker void GestureInterpreter::PushHardwareState(HardwareState* hwstate) {
455*aed3e508SAndroid Build Coastguard Worker   if (!interpreter_.get()) {
456*aed3e508SAndroid Build Coastguard Worker     Err("Filters are not composed yet!");
457*aed3e508SAndroid Build Coastguard Worker     return;
458*aed3e508SAndroid Build Coastguard Worker   }
459*aed3e508SAndroid Build Coastguard Worker   stime_t timeout = NO_DEADLINE;
460*aed3e508SAndroid Build Coastguard Worker   interpreter_->SyncInterpret(*hwstate, &timeout);
461*aed3e508SAndroid Build Coastguard Worker   if (timer_provider_ && interpret_timer_) {
462*aed3e508SAndroid Build Coastguard Worker     if (timeout == NO_DEADLINE) {
463*aed3e508SAndroid Build Coastguard Worker       timer_provider_->cancel_fn(timer_provider_data_, interpret_timer_);
464*aed3e508SAndroid Build Coastguard Worker     } else {
465*aed3e508SAndroid Build Coastguard Worker       timer_provider_->set_fn(timer_provider_data_,
466*aed3e508SAndroid Build Coastguard Worker                               interpret_timer_,
467*aed3e508SAndroid Build Coastguard Worker                               timeout,
468*aed3e508SAndroid Build Coastguard Worker                               InternalTimerCallback,
469*aed3e508SAndroid Build Coastguard Worker                               this);
470*aed3e508SAndroid Build Coastguard Worker       Log("Setting timer for %f s out.", timeout);
471*aed3e508SAndroid Build Coastguard Worker     }
472*aed3e508SAndroid Build Coastguard Worker   } else {
473*aed3e508SAndroid Build Coastguard Worker     ErrOnce("No timer provider has been set, so some features won't work.");
474*aed3e508SAndroid Build Coastguard Worker   }
475*aed3e508SAndroid Build Coastguard Worker }
476*aed3e508SAndroid Build Coastguard Worker 
SetHardwareProperties(const HardwareProperties & hwprops)477*aed3e508SAndroid Build Coastguard Worker void GestureInterpreter::SetHardwareProperties(
478*aed3e508SAndroid Build Coastguard Worker     const HardwareProperties& hwprops) {
479*aed3e508SAndroid Build Coastguard Worker   if (!interpreter_.get()) {
480*aed3e508SAndroid Build Coastguard Worker     Err("Filters are not composed yet!");
481*aed3e508SAndroid Build Coastguard Worker     return;
482*aed3e508SAndroid Build Coastguard Worker   }
483*aed3e508SAndroid Build Coastguard Worker   hwprops_ = hwprops;
484*aed3e508SAndroid Build Coastguard Worker   if (consumer_)
485*aed3e508SAndroid Build Coastguard Worker     interpreter_->Initialize(&hwprops_, nullptr, mprops_.get(),
486*aed3e508SAndroid Build Coastguard Worker                              consumer_.get());
487*aed3e508SAndroid Build Coastguard Worker }
488*aed3e508SAndroid Build Coastguard Worker 
TimerCallback(stime_t now,stime_t * timeout)489*aed3e508SAndroid Build Coastguard Worker void GestureInterpreter::TimerCallback(stime_t now, stime_t* timeout) {
490*aed3e508SAndroid Build Coastguard Worker   if (!interpreter_.get()) {
491*aed3e508SAndroid Build Coastguard Worker     Err("Filters are not composed yet!");
492*aed3e508SAndroid Build Coastguard Worker     return;
493*aed3e508SAndroid Build Coastguard Worker   }
494*aed3e508SAndroid Build Coastguard Worker   interpreter_->HandleTimer(now, timeout);
495*aed3e508SAndroid Build Coastguard Worker }
496*aed3e508SAndroid Build Coastguard Worker 
SetTimerProvider(GesturesTimerProvider * tp,void * data)497*aed3e508SAndroid Build Coastguard Worker void GestureInterpreter::SetTimerProvider(GesturesTimerProvider* tp,
498*aed3e508SAndroid Build Coastguard Worker                                           void* data) {
499*aed3e508SAndroid Build Coastguard Worker   if (timer_provider_ == tp && timer_provider_data_ == data)
500*aed3e508SAndroid Build Coastguard Worker     return;
501*aed3e508SAndroid Build Coastguard Worker   if (timer_provider_ && interpret_timer_) {
502*aed3e508SAndroid Build Coastguard Worker     timer_provider_->free_fn(timer_provider_data_, interpret_timer_);
503*aed3e508SAndroid Build Coastguard Worker     interpret_timer_ = nullptr;
504*aed3e508SAndroid Build Coastguard Worker   }
505*aed3e508SAndroid Build Coastguard Worker   if (interpret_timer_)
506*aed3e508SAndroid Build Coastguard Worker     Err("How was interpret_timer_ not null?!");
507*aed3e508SAndroid Build Coastguard Worker   timer_provider_ = tp;
508*aed3e508SAndroid Build Coastguard Worker   timer_provider_data_ = data;
509*aed3e508SAndroid Build Coastguard Worker   if (timer_provider_)
510*aed3e508SAndroid Build Coastguard Worker     interpret_timer_ = timer_provider_->create_fn(timer_provider_data_);
511*aed3e508SAndroid Build Coastguard Worker }
512*aed3e508SAndroid Build Coastguard Worker 
SetPropProvider(GesturesPropProvider * pp,void * data)513*aed3e508SAndroid Build Coastguard Worker void GestureInterpreter::SetPropProvider(GesturesPropProvider* pp,
514*aed3e508SAndroid Build Coastguard Worker                                          void* data) {
515*aed3e508SAndroid Build Coastguard Worker   prop_reg_->SetPropProvider(pp, data);
516*aed3e508SAndroid Build Coastguard Worker }
517*aed3e508SAndroid Build Coastguard Worker 
SetCallback(GestureReadyFunction callback,void * client_data)518*aed3e508SAndroid Build Coastguard Worker void GestureInterpreter::SetCallback(GestureReadyFunction callback,
519*aed3e508SAndroid Build Coastguard Worker                                      void* client_data) {
520*aed3e508SAndroid Build Coastguard Worker   callback_ = callback;
521*aed3e508SAndroid Build Coastguard Worker   callback_data_ = client_data;
522*aed3e508SAndroid Build Coastguard Worker 
523*aed3e508SAndroid Build Coastguard Worker   if (consumer_)
524*aed3e508SAndroid Build Coastguard Worker     consumer_->SetCallback(callback, client_data);
525*aed3e508SAndroid Build Coastguard Worker }
526*aed3e508SAndroid Build Coastguard Worker 
set_callback(GestureReadyFunction callback,void * client_data)527*aed3e508SAndroid Build Coastguard Worker void GestureInterpreter::set_callback(GestureReadyFunction callback,
528*aed3e508SAndroid Build Coastguard Worker                                       void* client_data) {
529*aed3e508SAndroid Build Coastguard Worker   SetCallback(callback, client_data);
530*aed3e508SAndroid Build Coastguard Worker }
531*aed3e508SAndroid Build Coastguard Worker 
InitializeTouchpad(void)532*aed3e508SAndroid Build Coastguard Worker void GestureInterpreter::InitializeTouchpad(void) {
533*aed3e508SAndroid Build Coastguard Worker   if (prop_reg_.get()) {
534*aed3e508SAndroid Build Coastguard Worker     stack_version_ = std::make_unique<IntProperty>(prop_reg_.get(),
535*aed3e508SAndroid Build Coastguard Worker                                                    "Touchpad Stack Version", 2);
536*aed3e508SAndroid Build Coastguard Worker     if (stack_version_->val_ == 2) {
537*aed3e508SAndroid Build Coastguard Worker       InitializeTouchpad2();
538*aed3e508SAndroid Build Coastguard Worker       return;
539*aed3e508SAndroid Build Coastguard Worker     }
540*aed3e508SAndroid Build Coastguard Worker   }
541*aed3e508SAndroid Build Coastguard Worker 
542*aed3e508SAndroid Build Coastguard Worker   Interpreter* temp = new ImmediateInterpreter(prop_reg_.get(), tracer_.get());
543*aed3e508SAndroid Build Coastguard Worker   temp = new FlingStopFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
544*aed3e508SAndroid Build Coastguard Worker                                         GESTURES_DEVCLASS_TOUCHPAD);
545*aed3e508SAndroid Build Coastguard Worker   temp = new ClickWiggleFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
546*aed3e508SAndroid Build Coastguard Worker   temp = new PalmClassifyingFilterInterpreter(prop_reg_.get(), temp,
547*aed3e508SAndroid Build Coastguard Worker                                               tracer_.get());
548*aed3e508SAndroid Build Coastguard Worker   temp = new IirFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
549*aed3e508SAndroid Build Coastguard Worker   temp = new LookaheadFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
550*aed3e508SAndroid Build Coastguard Worker   temp = new BoxFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
551*aed3e508SAndroid Build Coastguard Worker   temp = new StationaryWiggleFilterInterpreter(prop_reg_.get(), temp,
552*aed3e508SAndroid Build Coastguard Worker                                                tracer_.get());
553*aed3e508SAndroid Build Coastguard Worker   temp = new SensorJumpFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
554*aed3e508SAndroid Build Coastguard Worker   temp = new AccelFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
555*aed3e508SAndroid Build Coastguard Worker   temp = new SplitCorrectingFilterInterpreter(prop_reg_.get(), temp,
556*aed3e508SAndroid Build Coastguard Worker                                               tracer_.get());
557*aed3e508SAndroid Build Coastguard Worker   temp = new TrendClassifyingFilterInterpreter(prop_reg_.get(), temp,
558*aed3e508SAndroid Build Coastguard Worker                                                tracer_.get());
559*aed3e508SAndroid Build Coastguard Worker   temp = new MetricsFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
560*aed3e508SAndroid Build Coastguard Worker                                       GESTURES_DEVCLASS_TOUCHPAD);
561*aed3e508SAndroid Build Coastguard Worker   temp = new ScalingFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
562*aed3e508SAndroid Build Coastguard Worker                                       GESTURES_DEVCLASS_TOUCHPAD);
563*aed3e508SAndroid Build Coastguard Worker   temp = new FingerMergeFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
564*aed3e508SAndroid Build Coastguard Worker   temp = new StuckButtonInhibitorFilterInterpreter(temp, tracer_.get());
565*aed3e508SAndroid Build Coastguard Worker   temp = new HapticButtonGeneratorFilterInterpreter(prop_reg_.get(), temp,
566*aed3e508SAndroid Build Coastguard Worker                                                     tracer_.get());
567*aed3e508SAndroid Build Coastguard Worker   temp = new T5R2CorrectingFilterInterpreter(prop_reg_.get(), temp,
568*aed3e508SAndroid Build Coastguard Worker                                              tracer_.get());
569*aed3e508SAndroid Build Coastguard Worker   temp = new NonLinearityFilterInterpreter(prop_reg_.get(), temp,
570*aed3e508SAndroid Build Coastguard Worker                                            tracer_.get());
571*aed3e508SAndroid Build Coastguard Worker   temp = new TimestampFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
572*aed3e508SAndroid Build Coastguard Worker   temp = loggingFilter_ = new LoggingFilterInterpreter(prop_reg_.get(), temp,
573*aed3e508SAndroid Build Coastguard Worker                                                        tracer_.get());
574*aed3e508SAndroid Build Coastguard Worker   interpreter_.reset(temp);
575*aed3e508SAndroid Build Coastguard Worker   temp = nullptr;
576*aed3e508SAndroid Build Coastguard Worker }
577*aed3e508SAndroid Build Coastguard Worker 
InitializeTouchpad2(void)578*aed3e508SAndroid Build Coastguard Worker void GestureInterpreter::InitializeTouchpad2(void) {
579*aed3e508SAndroid Build Coastguard Worker   Interpreter* temp = new ImmediateInterpreter(prop_reg_.get(), tracer_.get());
580*aed3e508SAndroid Build Coastguard Worker   temp = new FlingStopFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
581*aed3e508SAndroid Build Coastguard Worker                                         GESTURES_DEVCLASS_TOUCHPAD);
582*aed3e508SAndroid Build Coastguard Worker   temp = new ClickWiggleFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
583*aed3e508SAndroid Build Coastguard Worker   temp = new PalmClassifyingFilterInterpreter(prop_reg_.get(), temp,
584*aed3e508SAndroid Build Coastguard Worker                                               tracer_.get());
585*aed3e508SAndroid Build Coastguard Worker   temp = new LookaheadFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
586*aed3e508SAndroid Build Coastguard Worker   temp = new BoxFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
587*aed3e508SAndroid Build Coastguard Worker   temp = new StationaryWiggleFilterInterpreter(prop_reg_.get(), temp,
588*aed3e508SAndroid Build Coastguard Worker                                                tracer_.get());
589*aed3e508SAndroid Build Coastguard Worker   temp = new AccelFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
590*aed3e508SAndroid Build Coastguard Worker   temp = new TrendClassifyingFilterInterpreter(prop_reg_.get(), temp,
591*aed3e508SAndroid Build Coastguard Worker                                                tracer_.get());
592*aed3e508SAndroid Build Coastguard Worker   temp = new MetricsFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
593*aed3e508SAndroid Build Coastguard Worker                                       GESTURES_DEVCLASS_TOUCHPAD);
594*aed3e508SAndroid Build Coastguard Worker   temp = new ScalingFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
595*aed3e508SAndroid Build Coastguard Worker                                       GESTURES_DEVCLASS_TOUCHPAD);
596*aed3e508SAndroid Build Coastguard Worker   temp = new FingerMergeFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
597*aed3e508SAndroid Build Coastguard Worker   temp = new StuckButtonInhibitorFilterInterpreter(temp, tracer_.get());
598*aed3e508SAndroid Build Coastguard Worker   temp = new HapticButtonGeneratorFilterInterpreter(prop_reg_.get(), temp,
599*aed3e508SAndroid Build Coastguard Worker                                                     tracer_.get());
600*aed3e508SAndroid Build Coastguard Worker   temp = new TimestampFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
601*aed3e508SAndroid Build Coastguard Worker   temp = loggingFilter_ = new LoggingFilterInterpreter(prop_reg_.get(), temp,
602*aed3e508SAndroid Build Coastguard Worker                                                        tracer_.get());
603*aed3e508SAndroid Build Coastguard Worker   interpreter_.reset(temp);
604*aed3e508SAndroid Build Coastguard Worker   temp = nullptr;
605*aed3e508SAndroid Build Coastguard Worker }
606*aed3e508SAndroid Build Coastguard Worker 
InitializeMouse(GestureInterpreterDeviceClass cls)607*aed3e508SAndroid Build Coastguard Worker void GestureInterpreter::InitializeMouse(GestureInterpreterDeviceClass cls) {
608*aed3e508SAndroid Build Coastguard Worker   Interpreter* temp = new MouseInterpreter(prop_reg_.get(), tracer_.get());
609*aed3e508SAndroid Build Coastguard Worker   // TODO(clchiou;chromium-os:36321): Use mouse acceleration algorithm for mice
610*aed3e508SAndroid Build Coastguard Worker   temp = new AccelFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
611*aed3e508SAndroid Build Coastguard Worker   temp = new ScalingFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
612*aed3e508SAndroid Build Coastguard Worker                                       cls);
613*aed3e508SAndroid Build Coastguard Worker   temp = new MetricsFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
614*aed3e508SAndroid Build Coastguard Worker                                       cls);
615*aed3e508SAndroid Build Coastguard Worker   temp = new IntegralGestureFilterInterpreter(temp, tracer_.get());
616*aed3e508SAndroid Build Coastguard Worker   temp = loggingFilter_ = new LoggingFilterInterpreter(prop_reg_.get(), temp,
617*aed3e508SAndroid Build Coastguard Worker                                                        tracer_.get());
618*aed3e508SAndroid Build Coastguard Worker   interpreter_.reset(temp);
619*aed3e508SAndroid Build Coastguard Worker   temp = nullptr;
620*aed3e508SAndroid Build Coastguard Worker }
621*aed3e508SAndroid Build Coastguard Worker 
InitializeMultitouchMouse(void)622*aed3e508SAndroid Build Coastguard Worker void GestureInterpreter::InitializeMultitouchMouse(void) {
623*aed3e508SAndroid Build Coastguard Worker   Interpreter* temp = new MultitouchMouseInterpreter(prop_reg_.get(),
624*aed3e508SAndroid Build Coastguard Worker                                                      tracer_.get());
625*aed3e508SAndroid Build Coastguard Worker   temp = new FlingStopFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
626*aed3e508SAndroid Build Coastguard Worker                                         GESTURES_DEVCLASS_MULTITOUCH_MOUSE);
627*aed3e508SAndroid Build Coastguard Worker   temp = new ClickWiggleFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
628*aed3e508SAndroid Build Coastguard Worker   temp = new LookaheadFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
629*aed3e508SAndroid Build Coastguard Worker   temp = new BoxFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
630*aed3e508SAndroid Build Coastguard Worker   // TODO(clchiou;chromium-os:36321): Use mouse acceleration algorithm for mice
631*aed3e508SAndroid Build Coastguard Worker   temp = new AccelFilterInterpreter(prop_reg_.get(), temp, tracer_.get());
632*aed3e508SAndroid Build Coastguard Worker   temp = new ScalingFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
633*aed3e508SAndroid Build Coastguard Worker                                       GESTURES_DEVCLASS_MULTITOUCH_MOUSE);
634*aed3e508SAndroid Build Coastguard Worker   temp = new MetricsFilterInterpreter(prop_reg_.get(), temp, tracer_.get(),
635*aed3e508SAndroid Build Coastguard Worker                                       GESTURES_DEVCLASS_MULTITOUCH_MOUSE);
636*aed3e508SAndroid Build Coastguard Worker   temp = new IntegralGestureFilterInterpreter(temp, tracer_.get());
637*aed3e508SAndroid Build Coastguard Worker   temp = new StuckButtonInhibitorFilterInterpreter(temp, tracer_.get());
638*aed3e508SAndroid Build Coastguard Worker   temp = new NonLinearityFilterInterpreter(prop_reg_.get(), temp,
639*aed3e508SAndroid Build Coastguard Worker                                            tracer_.get());
640*aed3e508SAndroid Build Coastguard Worker   temp = loggingFilter_ = new LoggingFilterInterpreter(prop_reg_.get(), temp,
641*aed3e508SAndroid Build Coastguard Worker                                                        tracer_.get());
642*aed3e508SAndroid Build Coastguard Worker   interpreter_.reset(temp);
643*aed3e508SAndroid Build Coastguard Worker   temp = nullptr;
644*aed3e508SAndroid Build Coastguard Worker }
645*aed3e508SAndroid Build Coastguard Worker 
Initialize(GestureInterpreterDeviceClass cls)646*aed3e508SAndroid Build Coastguard Worker void GestureInterpreter::Initialize(GestureInterpreterDeviceClass cls) {
647*aed3e508SAndroid Build Coastguard Worker   if (cls == GESTURES_DEVCLASS_TOUCHPAD ||
648*aed3e508SAndroid Build Coastguard Worker       cls == GESTURES_DEVCLASS_TOUCHSCREEN)
649*aed3e508SAndroid Build Coastguard Worker     InitializeTouchpad();
650*aed3e508SAndroid Build Coastguard Worker   else if (cls == GESTURES_DEVCLASS_MOUSE ||
651*aed3e508SAndroid Build Coastguard Worker            cls == GESTURES_DEVCLASS_POINTING_STICK)
652*aed3e508SAndroid Build Coastguard Worker     InitializeMouse(cls);
653*aed3e508SAndroid Build Coastguard Worker   else if (cls == GESTURES_DEVCLASS_MULTITOUCH_MOUSE)
654*aed3e508SAndroid Build Coastguard Worker     InitializeMultitouchMouse();
655*aed3e508SAndroid Build Coastguard Worker   else
656*aed3e508SAndroid Build Coastguard Worker     Err("Couldn't recognize device class: %d", cls);
657*aed3e508SAndroid Build Coastguard Worker 
658*aed3e508SAndroid Build Coastguard Worker   mprops_.reset(new MetricsProperties(prop_reg_.get()));
659*aed3e508SAndroid Build Coastguard Worker   consumer_.reset(new GestureInterpreterConsumer(callback_,
660*aed3e508SAndroid Build Coastguard Worker                                                    callback_data_));
661*aed3e508SAndroid Build Coastguard Worker }
662*aed3e508SAndroid Build Coastguard Worker 
EncodeActivityLog()663*aed3e508SAndroid Build Coastguard Worker std::string GestureInterpreter::EncodeActivityLog() {
664*aed3e508SAndroid Build Coastguard Worker   return loggingFilter_->EncodeActivityLog();
665*aed3e508SAndroid Build Coastguard Worker }
666*aed3e508SAndroid Build Coastguard Worker 
667*aed3e508SAndroid Build Coastguard Worker const GestureMove kGestureMove = { 0, 0, 0, 0 };
668*aed3e508SAndroid Build Coastguard Worker const GestureScroll kGestureScroll = { 0, 0, 0, 0, 0 };
669*aed3e508SAndroid Build Coastguard Worker const GestureMouseWheel kGestureMouseWheel = { 0, 0, 0, 0 };
670*aed3e508SAndroid Build Coastguard Worker const GestureButtonsChange kGestureButtonsChange = { 0, 0, 0 };
671*aed3e508SAndroid Build Coastguard Worker const GestureFling kGestureFling = { 0, 0, 0, 0, 0 };
672*aed3e508SAndroid Build Coastguard Worker const GestureSwipe kGestureSwipe = { 0, 0, 0, 0 };
673*aed3e508SAndroid Build Coastguard Worker const GestureFourFingerSwipe kGestureFourFingerSwipe = { 0, 0, 0, 0 };
674*aed3e508SAndroid Build Coastguard Worker const GesturePinch kGesturePinch = { 0, 0, 0 };
675*aed3e508SAndroid Build Coastguard Worker const GestureSwipeLift kGestureSwipeLift = { };
676*aed3e508SAndroid Build Coastguard Worker const GestureFourFingerSwipeLift kGestureFourFingerSwipeLift = { };
677*aed3e508SAndroid Build Coastguard Worker const GestureMetrics kGestureMetrics = { kGestureMetricsTypeUnknown, {0, 0} };
678