• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "include/activity_replay.h"
6 
7 #include <limits.h>
8 #include <set>
9 #include <string>
10 
11 #include <gtest/gtest.h>
12 #include <json/reader.h>
13 #include <json/writer.h>
14 
15 #include "include/logging.h"
16 #include "include/prop_registry.h"
17 #include "include/unittest_util.h"
18 #include "include/util.h"
19 
20 using std::endl;
21 using std::set;
22 using std::string;
23 
24 namespace {
25 
26 // Helper to std::visit with lambdas.
27 template <typename... V>
28 struct Visitor : V... {
29   using V::operator()...;
30 };
31 // Explicit deduction guide (not needed as of C++20).
32 template <typename... V>
33 Visitor(V...) -> Visitor<V...>;
34 
35 } // namespace
36 
37 namespace gestures {
38 
ActivityReplay(PropRegistry * prop_reg)39 ActivityReplay::ActivityReplay(PropRegistry* prop_reg)
40     : log_(nullptr), prop_reg_(prop_reg) {}
41 
Parse(const string & data)42 bool ActivityReplay::Parse(const string& data) {
43   std::set<string> emptyset;
44   return Parse(data, emptyset);
45 }
46 
Parse(const string & data,const std::set<string> & honor_props)47 bool ActivityReplay::Parse(const string& data,
48                            const std::set<string>& honor_props) {
49   log_.Clear();
50   names_.clear();
51 
52   string error_msg;
53   Json::Value root;
54   {
55     Json::CharReaderBuilder builder;
56     std::unique_ptr<Json::CharReader> const reader(builder.newCharReader());
57     const char * const data_str = data.c_str();
58 
59     if (!reader->parse(data_str, data_str + data.size(),
60                        &root, &error_msg)) {  // root modified in parse()
61       Err("Parse failed: %s", error_msg.c_str());
62       return false;
63     }
64   }
65   if (root.type() != Json::objectValue) {
66     Err("Root type is %d, but expected %d (dictionary)",
67         root.type(), Json::objectValue);
68     return false;
69   }
70   // Get and apply user-configurable properties
71   Json::Value props_dict =
72       root.get(ActivityLog::kKeyProperties, Json::Value());
73   if (root.isMember(ActivityLog::kKeyProperties) &&
74       !ParseProperties(props_dict, honor_props)) {
75     Err("Unable to parse properties.");
76     return false;
77   }
78   // Get and apply hardware properties
79   if (!root.isMember(ActivityLog::kKeyHardwarePropRoot)) {
80     Err("Unable to get hwprops dict.");
81     return false;
82   }
83   Json::Value hwprops_dict =
84       root.get(ActivityLog::kKeyHardwarePropRoot, Json::Value());
85   if (!ParseHardwareProperties(hwprops_dict, &hwprops_))
86     return false;
87   log_.SetHardwareProperties(hwprops_);
88   Json::Value entries = root.get(ActivityLog::kKeyRoot, Json::Value());
89   char next_layer_path[PATH_MAX];
90   snprintf(next_layer_path, sizeof(next_layer_path), "%s.%s",
91            ActivityLog::kKeyNext, ActivityLog::kKeyRoot);
92   if (!root.isMember(ActivityLog::kKeyRoot)) {
93     Err("Unable to get list of entries from root.");
94     return false;
95   }
96   if (root.isMember(next_layer_path)) {
97     Json::Value next_layer_entries = root[next_layer_path];
98     if (entries.size() < next_layer_entries.size())
99       entries = next_layer_entries;
100   }
101 
102   for (size_t i = 0; i < entries.size(); ++i) {
103     Json::Value entry = entries.get(i, Json::Value());
104     if (!entries.isValidIndex(i)) {
105       Err("Invalid entry at index %zu", i);
106       return false;
107     }
108     if (!ParseEntry(entry))
109       return false;
110   }
111   return true;
112 }
113 
ParseProperties(const Json::Value & dict,const std::set<string> & honor_props)114 bool ActivityReplay::ParseProperties(const Json::Value& dict,
115                                      const std::set<string>& honor_props) {
116   if (!prop_reg_)
117     return true;
118   ::set<Property*> props = prop_reg_->props();
119   for (::set<Property*>::const_iterator it = props.begin(), e = props.end();
120        it != e; ++it) {
121     const char* key = (*it)->name();
122 
123     // TODO(clchiou): This is just a emporary workaround for property changes.
124     // I will work out a solution for this kind of changes.
125     if (!strcmp(key, "Compute Surface Area from Pressure") ||
126         !strcmp(key, "Touchpad Device Output Bias on X-Axis") ||
127         !strcmp(key, "Touchpad Device Output Bias on Y-Axis")) {
128       continue;
129     }
130 
131     if (!honor_props.empty() && !SetContainsValue(honor_props, string(key)))
132       continue;
133     if (!dict.isMember(key)) {
134       Err("Log doesn't have value for property %s", key);
135       continue;
136     }
137     const Json::Value& value = dict[key];
138     if (!(*it)->SetValue(value)) {
139       Err("Unable to restore value for property %s", key);
140       return false;
141     }
142   }
143   return true;
144 }
145 
146 #define PARSE_HP(obj, key, IsTypeFn, KeyFn, var, VarType, required)      \
147   do {                                                                  \
148     if (!obj.isMember(key) || !obj[key].IsTypeFn()) {                   \
149       Err("Parse failed for key %s", key);                              \
150       if (required)                                                     \
151         return false;                                                   \
152     }                                                                   \
153     var = obj[key].KeyFn();                                             \
154   } while (0)
155 
ParseHardwareProperties(const Json::Value & obj,HardwareProperties * out_props)156 bool ActivityReplay::ParseHardwareProperties(const Json::Value& obj,
157                                              HardwareProperties* out_props) {
158   HardwareProperties props;
159   PARSE_HP(obj, ActivityLog::kKeyHardwarePropLeft, isDouble, asDouble,
160            props.left, float, true);
161   PARSE_HP(obj, ActivityLog::kKeyHardwarePropTop, isDouble, asDouble,
162            props.top, float, true);
163   PARSE_HP(obj, ActivityLog::kKeyHardwarePropRight, isDouble, asDouble,
164            props.right, float, true);
165   PARSE_HP(obj, ActivityLog::kKeyHardwarePropBottom, isDouble, asDouble,
166            props.bottom, float, true);
167   PARSE_HP(obj, ActivityLog::kKeyHardwarePropXResolution, isDouble, asDouble,
168            props.res_x, float, true);
169   PARSE_HP(obj, ActivityLog::kKeyHardwarePropYResolution, isDouble, asDouble,
170            props.res_y, float, true);
171   PARSE_HP(obj, ActivityLog::kKeyHardwarePropXDpi, isDouble, asDouble,
172            props.screen_x_dpi, float, true);
173   PARSE_HP(obj, ActivityLog::kKeyHardwarePropYDpi, isDouble, asDouble,
174            props.screen_y_dpi, float, true);
175   PARSE_HP(obj, ActivityLog::kKeyHardwarePropOrientationMinimum,
176            isDouble, asDouble, props.orientation_minimum, float, false);
177   PARSE_HP(obj, ActivityLog::kKeyHardwarePropOrientationMaximum,
178            isDouble, asDouble, props.orientation_maximum, float, false);
179   PARSE_HP(obj, ActivityLog::kKeyHardwarePropMaxFingerCount, isInt, asUInt,
180            props.max_finger_cnt, unsigned short, true);
181   PARSE_HP(obj, ActivityLog::kKeyHardwarePropMaxTouchCount, isInt, asUInt,
182            props.max_touch_cnt, unsigned short, true);
183   PARSE_HP(obj, ActivityLog::kKeyHardwarePropSupportsT5R2, isBool, asBool,
184            props.supports_t5r2, bool, true);
185   PARSE_HP(obj, ActivityLog::kKeyHardwarePropSemiMt,isBool, asBool,
186            props.support_semi_mt, bool, true);
187   PARSE_HP(obj, ActivityLog::kKeyHardwarePropIsButtonPad,isBool, asBool,
188            props.is_button_pad, bool, true);
189   PARSE_HP(obj, ActivityLog::kKeyHardwarePropHasWheel,isBool, asBool,
190            props.has_wheel, bool, true);
191   *out_props = props;
192   return true;
193 }
194 
195 #undef PARSE_HP
196 
ParseEntry(const Json::Value & entry)197 bool ActivityReplay::ParseEntry(const Json::Value& entry) {
198   if (!entry.isMember(ActivityLog::kKeyType) ||
199       entry[ActivityLog::kKeyType].type() != Json::stringValue) {
200     Err("Can't get entry type.");
201     return false;
202   }
203   string type = entry[ActivityLog::kKeyType].asString();
204   if (type == ActivityLog::kKeyHardwareState)
205     return ParseHardwareState(entry);
206   if (type == ActivityLog::kKeyTimerCallback)
207     return ParseTimerCallback(entry);
208   if (type == ActivityLog::kKeyCallbackRequest)
209     return ParseCallbackRequest(entry);
210   if (type == ActivityLog::kKeyGesture)
211     return ParseGesture(entry);
212   if (type == ActivityLog::kKeyPropChange)
213     return ParsePropChange(entry);
214   Err("Unknown entry type");
215   return false;
216 }
217 
ParseHardwareState(const Json::Value & entry)218 bool ActivityReplay::ParseHardwareState(const Json::Value& entry) {
219   HardwareState hs = HardwareState();
220   if (!entry.isMember(ActivityLog::kKeyHardwareStateButtonsDown)) {
221     Err("Unable to parse hardware state buttons down");
222     return false;
223   }
224   hs.buttons_down = entry[ActivityLog::kKeyHardwareStateButtonsDown].asUInt();
225   if (!entry.isMember(ActivityLog::kKeyHardwareStateTouchCnt)) {
226     Err("Unable to parse hardware state touch count");
227     return false;
228   }
229   hs.touch_cnt = entry[ActivityLog::kKeyHardwareStateTouchCnt].asUInt();
230   if (!entry.isMember(ActivityLog::kKeyHardwareStateTimestamp)) {
231     Err("Unable to parse hardware state timestamp");
232     return false;
233   }
234   hs.timestamp = entry[ActivityLog::kKeyHardwareStateTimestamp].asDouble();
235   if (!entry.isMember(ActivityLog::kKeyHardwareStateFingers)) {
236     Err("Unable to parse hardware state fingers");
237     return false;
238   }
239   Json::Value fingers = entry[ActivityLog::kKeyHardwareStateFingers];
240   // Sanity check
241   if (fingers.size() > 30) {
242     Err("Too many fingers in hardware state");
243     return false;
244   }
245   FingerState fs[fingers.size()];
246   for (size_t i = 0; i < fingers.size(); ++i) {
247     if (!fingers.isValidIndex(i)) {
248       Err("Invalid entry at index %zu", i);
249       return false;
250     }
251     const Json::Value& finger_state = fingers[static_cast<int>(i)];
252     if (!ParseFingerState(finger_state, &fs[i]))
253       return false;
254   }
255   hs.fingers = fs;
256   hs.finger_cnt = fingers.size();
257   // There may not have rel_ entries for old logs
258   if (entry.isMember(ActivityLog::kKeyHardwareStateRelX)) {
259     hs.rel_x = entry[ActivityLog::kKeyHardwareStateRelX].asDouble();
260     if (!entry.isMember(ActivityLog::kKeyHardwareStateRelY)) {
261       Err("Unable to parse hardware state rel_y");
262       return false;
263     }
264     hs.rel_x = entry[ActivityLog::kKeyHardwareStateRelY].asDouble();
265     if (!entry.isMember(ActivityLog::kKeyHardwareStateRelWheel)) {
266       Err("Unable to parse hardware state rel_wheel");
267       return false;
268     }
269     hs.rel_wheel = entry[ActivityLog::kKeyHardwareStateRelWheel].asDouble();
270     if (!entry.isMember(ActivityLog::kKeyHardwareStateRelHWheel)) {
271       Err("Unable to parse hardware state rel_hwheel");
272       return false;
273     }
274     hs.rel_hwheel = entry[ActivityLog::kKeyHardwareStateRelHWheel].asDouble();
275   }
276   log_.LogHardwareState(hs);
277   return true;
278 }
279 
ParseFingerState(const Json::Value & entry,FingerState * out_fs)280 bool ActivityReplay::ParseFingerState(const Json::Value& entry,
281                                       FingerState* out_fs) {
282   if (!entry.isMember(ActivityLog::kKeyFingerStateTouchMajor)) {
283     Err("can't parse finger's touch major");
284     return false;
285   }
286   out_fs->touch_major =
287       entry[ActivityLog::kKeyFingerStateTouchMajor].asDouble();
288   if (!entry.isMember(ActivityLog::kKeyFingerStateTouchMinor)) {
289     Err("can't parse finger's touch minor");
290     return false;
291   }
292   out_fs->touch_minor =
293       entry[ActivityLog::kKeyFingerStateTouchMinor].asDouble();
294   if (!entry.isMember(ActivityLog::kKeyFingerStateWidthMajor)) {
295     Err("can't parse finger's width major");
296     return false;
297   }
298   out_fs->width_major =
299       entry[ActivityLog::kKeyFingerStateWidthMajor].asDouble();
300   if (!entry.isMember(ActivityLog::kKeyFingerStateWidthMinor)) {
301     Err("can't parse finger's width minor");
302     return false;
303   }
304   out_fs->width_minor =
305       entry[ActivityLog::kKeyFingerStateWidthMinor].asDouble();
306   if (!entry.isMember(ActivityLog::kKeyFingerStatePressure)) {
307     Err("can't parse finger's pressure");
308     return false;
309   }
310   out_fs->pressure = entry[ActivityLog::kKeyFingerStatePressure].asDouble();
311   if (!entry.isMember(ActivityLog::kKeyFingerStateOrientation)) {
312     Err("can't parse finger's orientation");
313     return false;
314   }
315   out_fs->orientation =
316       entry[ActivityLog::kKeyFingerStateOrientation].asDouble();
317   if (!entry.isMember(ActivityLog::kKeyFingerStatePositionX)) {
318     Err("can't parse finger's position x");
319     return false;
320   }
321   out_fs->position_x = entry[ActivityLog::kKeyFingerStatePositionX].asDouble();
322   if (!entry.isMember(ActivityLog::kKeyFingerStatePositionY)) {
323     Err("can't parse finger's position y");
324     return false;
325   }
326   out_fs->position_y = entry[ActivityLog::kKeyFingerStatePositionY].asDouble();
327   if (!entry.isMember(ActivityLog::kKeyFingerStateTrackingId)) {
328     Err("can't parse finger's tracking id");
329     return false;
330   }
331   out_fs->tracking_id = entry[ActivityLog::kKeyFingerStateTrackingId].asInt();
332   if (!entry.isMember(ActivityLog::kKeyFingerStateFlags))
333     Err("can't parse finger's flags; continuing.");
334   out_fs->flags = entry[ActivityLog::kKeyFingerStateFlags].asUInt();
335   return true;
336 }
337 
ParseTimerCallback(const Json::Value & entry)338 bool ActivityReplay::ParseTimerCallback(const Json::Value& entry) {
339   if (!entry.isMember(ActivityLog::kKeyTimerNow)) {
340     Err("can't parse timercallback");
341     return false;
342   }
343   log_.LogTimerCallback(entry[ActivityLog::kKeyTimerNow].asDouble());
344   return true;
345 }
346 
ParseCallbackRequest(const Json::Value & entry)347 bool ActivityReplay::ParseCallbackRequest(const Json::Value& entry) {
348   if (!entry.isMember(ActivityLog::kKeyCallbackRequestWhen)) {
349     Err("can't parse callback request");
350     return false;
351   }
352   log_.LogCallbackRequest(
353       entry[ActivityLog::kKeyCallbackRequestWhen].asDouble());
354   return true;
355 }
356 
ParseGesture(const Json::Value & entry)357 bool ActivityReplay::ParseGesture(const Json::Value& entry) {
358   if (!entry.isMember(ActivityLog::kKeyGestureType)) {
359     Err("can't parse gesture type");
360     return false;
361   }
362   string gesture_type = entry[ActivityLog::kKeyGestureType].asString();
363   Gesture gs;
364 
365   if (!entry.isMember(ActivityLog::kKeyGestureStartTime)) {
366     Err("Failed to parse gesture start time");
367     return false;
368   }
369   gs.start_time = entry[ActivityLog::kKeyGestureStartTime].asDouble();
370   if (!entry.isMember(ActivityLog::kKeyGestureEndTime)) {
371     Err("Failed to parse gesture end time");
372     return false;
373   }
374   gs.end_time = entry[ActivityLog::kKeyGestureEndTime].asDouble();
375 
376   if (gesture_type == ActivityLog::kValueGestureTypeContactInitiated) {
377     gs.type = kGestureTypeContactInitiated;
378   } else if (gesture_type == ActivityLog::kValueGestureTypeMove) {
379     if (!ParseGestureMove(entry, &gs))
380       return false;
381   } else if (gesture_type == ActivityLog::kValueGestureTypeScroll) {
382     if (!ParseGestureScroll(entry, &gs))
383       return false;
384   } else if (gesture_type == ActivityLog::kValueGestureTypeSwipe) {
385     if (!ParseGestureSwipe(entry, &gs))
386       return false;
387   } else if (gesture_type == ActivityLog::kValueGestureTypeSwipeLift) {
388     if (!ParseGestureSwipeLift(entry, &gs))
389       return false;
390   } else if (gesture_type == ActivityLog::kValueGestureTypePinch) {
391     if (!ParseGesturePinch(entry, &gs))
392       return false;
393   } else if (gesture_type == ActivityLog::kValueGestureTypeButtonsChange) {
394     if (!ParseGestureButtonsChange(entry, &gs))
395       return false;
396   } else if (gesture_type == ActivityLog::kValueGestureTypeFling) {
397     if (!ParseGestureFling(entry, &gs))
398       return false;
399   } else if (gesture_type == ActivityLog::kValueGestureTypeMetrics) {
400     if (!ParseGestureMetrics(entry, &gs))
401       return false;
402   } else {
403     gs.type = kGestureTypeNull;
404   }
405   log_.LogGesture(gs);
406   return true;
407 }
408 
ParseGestureMove(const Json::Value & entry,Gesture * out_gs)409 bool ActivityReplay::ParseGestureMove(const Json::Value& entry,
410                                       Gesture* out_gs) {
411   out_gs->type = kGestureTypeMove;
412   if (!entry.isMember(ActivityLog::kKeyGestureDX)) {
413     Err("can't parse move dx");
414     return false;
415   }
416   out_gs->details.move.dx = entry[ActivityLog::kKeyGestureDX].asDouble();
417   if (!entry.isMember(ActivityLog::kKeyGestureDY)) {
418     Err("can't parse move dy");
419     return false;
420   }
421   out_gs->details.move.dy = entry[ActivityLog::kKeyGestureDY].asDouble();
422   if (!entry.isMember(ActivityLog::kKeyGestureOrdinalDX)) {
423     Err("can't parse move ordinal_dx");
424     return false;
425   }
426   out_gs->details.move.ordinal_dx =
427       entry[ActivityLog::kKeyGestureOrdinalDX].asDouble();
428   if (!entry.isMember(ActivityLog::kKeyGestureOrdinalDY)) {
429     Err("can't parse move ordinal_dy");
430     return false;
431   }
432   out_gs->details.move.ordinal_dy =
433       entry[ActivityLog::kKeyGestureOrdinalDY].asDouble();
434   return true;
435 }
436 
ParseGestureScroll(const Json::Value & entry,Gesture * out_gs)437 bool ActivityReplay::ParseGestureScroll(const Json::Value& entry,
438                                         Gesture* out_gs) {
439   out_gs->type = kGestureTypeScroll;
440   if (!entry.isMember(ActivityLog::kKeyGestureDX)) {
441     Err("can't parse scroll dx");
442     return false;
443   }
444   out_gs->details.scroll.dx =
445       entry[ActivityLog::kKeyGestureDX].asDouble();
446   if (!entry.isMember(ActivityLog::kKeyGestureDY)) {
447     Err("can't parse scroll dy");
448     return false;
449   }
450   out_gs->details.scroll.dy =
451       entry[ActivityLog::kKeyGestureDY].asDouble();
452   if (!entry.isMember(ActivityLog::kKeyGestureOrdinalDX)) {
453     Err("can't parse scroll ordinal_dx");
454     return false;
455   }
456   out_gs->details.scroll.ordinal_dx =
457       entry[ActivityLog::kKeyGestureOrdinalDX].asDouble();
458   if (!entry.isMember(ActivityLog::kKeyGestureOrdinalDY)) {
459     Err("can't parse scroll ordinal_dy");
460     return false;
461   }
462   out_gs->details.scroll.ordinal_dy =
463       entry[ActivityLog::kKeyGestureOrdinalDY].asDouble();
464   return true;
465 }
466 
ParseGestureSwipe(const Json::Value & entry,Gesture * out_gs)467 bool ActivityReplay::ParseGestureSwipe(const Json::Value& entry,
468                                        Gesture* out_gs) {
469   out_gs->type = kGestureTypeSwipe;
470   if (!entry.isMember(ActivityLog::kKeyGestureDX)) {
471     Err("can't parse swipe dx");
472     return false;
473   }
474   out_gs->details.swipe.dx = entry[ActivityLog::kKeyGestureDX].asDouble();
475   if (!entry.isMember(ActivityLog::kKeyGestureDY)) {
476     Err("can't parse swipe dy");
477     return false;
478   }
479   out_gs->details.swipe.dy = entry[ActivityLog::kKeyGestureDY].asDouble();
480   if (!entry.isMember(ActivityLog::kKeyGestureOrdinalDX)) {
481     Err("can't parse swipe ordinal_dx");
482     return false;
483   }
484   out_gs->details.swipe.ordinal_dx =
485       entry[ActivityLog::kKeyGestureOrdinalDX].asDouble();
486   if (!entry.isMember(ActivityLog::kKeyGestureOrdinalDY)) {
487     Err("can't parse swipe ordinal_dy");
488     return false;
489   }
490   out_gs->details.swipe.ordinal_dy =
491       entry[ActivityLog::kKeyGestureOrdinalDY].asDouble();
492   return true;
493 }
494 
ParseGestureSwipeLift(const Json::Value & entry,Gesture * out_gs)495 bool ActivityReplay::ParseGestureSwipeLift(const Json::Value& entry,
496                                            Gesture* out_gs) {
497   out_gs->type = kGestureTypeSwipeLift;
498   return true;
499 }
500 
ParseGesturePinch(const Json::Value & entry,Gesture * out_gs)501 bool ActivityReplay::ParseGesturePinch(const Json::Value& entry,
502                                        Gesture* out_gs) {
503   out_gs->type = kGestureTypePinch;
504   if (!entry.isMember(ActivityLog::kKeyGesturePinchDZ)) {
505     Err("can't parse pinch dz");
506     return false;
507   }
508   out_gs->details.pinch.dz = entry[ActivityLog::kKeyGesturePinchDZ].asDouble();
509   if (!entry.isMember(ActivityLog::kKeyGesturePinchOrdinalDZ)) {
510     Err("can't parse pinch ordinal_dz");
511     return false;
512   }
513   out_gs->details.pinch.ordinal_dz =
514       entry[ActivityLog::kKeyGesturePinchOrdinalDZ].asDouble();
515   if (!entry.isMember(ActivityLog::kKeyGesturePinchZoomState)) {
516     Err("can't parse pinch zoom_state");
517     return false;
518   }
519   out_gs->details.pinch.zoom_state =
520       entry[ActivityLog::kKeyGesturePinchZoomState].asInt();
521   return true;
522 }
523 
ParseGestureButtonsChange(const Json::Value & entry,Gesture * out_gs)524 bool ActivityReplay::ParseGestureButtonsChange(const Json::Value& entry,
525                                                Gesture* out_gs) {
526   out_gs->type = kGestureTypeButtonsChange;
527   if (!entry.isMember(ActivityLog::kKeyGestureButtonsChangeDown)) {
528     Err("can't parse buttons down");
529     return false;
530   }
531   out_gs->details.buttons.down =
532       entry[ActivityLog::kKeyGestureButtonsChangeDown].asUInt();
533   if (!entry.isMember(ActivityLog::kKeyGestureButtonsChangeUp)) {
534     Err("can't parse buttons up");
535     return false;
536   }
537   out_gs->details.buttons.up =
538       entry[ActivityLog::kKeyGestureButtonsChangeUp].asUInt();
539   return true;
540 }
541 
ParseGestureFling(const Json::Value & entry,Gesture * out_gs)542 bool ActivityReplay::ParseGestureFling(const Json::Value& entry,
543                                        Gesture* out_gs) {
544   out_gs->type = kGestureTypeFling;
545   if (!entry.isMember(ActivityLog::kKeyGestureFlingVX)) {
546     Err("can't parse fling vx");
547     return false;
548   }
549   out_gs->details.fling.vx = entry[ActivityLog::kKeyGestureFlingVX].asDouble();
550   if (!entry.isMember(ActivityLog::kKeyGestureFlingVY)) {
551     Err("can't parse fling vy");
552     return false;
553   }
554   out_gs->details.fling.vy = entry[ActivityLog::kKeyGestureFlingVY].asDouble();
555   if (!entry.isMember(ActivityLog::kKeyGestureFlingOrdinalVX)) {
556     Err("can't parse fling ordinal_vx");
557     return false;
558   }
559   out_gs->details.fling.ordinal_vx =
560       entry[ActivityLog::kKeyGestureFlingOrdinalVX].asDouble();
561   if (!entry.isMember(ActivityLog::kKeyGestureFlingOrdinalVY)) {
562     Err("can't parse fling ordinal_vy");
563     return false;
564   }
565   out_gs->details.fling.ordinal_vy =
566       entry[ActivityLog::kKeyGestureFlingOrdinalVY].asDouble();
567   if (!entry.isMember(ActivityLog::kKeyGestureFlingState)) {
568     Err("can't parse scroll is_scroll_begin");
569     return false;
570   }
571   out_gs->details.fling.fling_state =
572       entry[ActivityLog::kKeyGestureFlingState].asInt();
573   return true;
574 }
575 
ParseGestureMetrics(const Json::Value & entry,Gesture * out_gs)576 bool ActivityReplay::ParseGestureMetrics(const Json::Value& entry,
577                                        Gesture* out_gs) {
578   out_gs->type = kGestureTypeMetrics;
579   if (!entry.isMember(ActivityLog::kKeyGestureMetricsData1)) {
580     Err("can't parse metrics data 1");
581     return false;
582   }
583   out_gs->details.metrics.data[0] =
584       entry[ActivityLog::kKeyGestureMetricsData1].asDouble();
585   if (!entry.isMember(ActivityLog::kKeyGestureMetricsData2)) {
586     Err("can't parse metrics data 2");
587     return false;
588   }
589   out_gs->details.metrics.data[1] =
590       entry[ActivityLog::kKeyGestureMetricsData2].asDouble();
591   if (!entry.isMember(ActivityLog::kKeyGestureMetricsType)) {
592     Err("can't parse metrics type");
593     return false;
594   }
595   int type = entry[ActivityLog::kKeyGestureMetricsType].asInt();
596   if (type == 0) {
597     out_gs->details.metrics.type = kGestureMetricsTypeNoisyGround;
598     return true;
599   }
600   out_gs->details.metrics.type = kGestureMetricsTypeUnknown;
601   return true;
602 }
603 
ParsePropChange(const Json::Value & entry)604 bool ActivityReplay::ParsePropChange(const Json::Value& entry) {
605   ActivityLog::PropChangeEntry prop_change;
606   if (!entry.isMember(ActivityLog::kKeyPropChangeType)) {
607     Err("Can't get prop change type");
608     return false;
609   }
610   string type = entry[ActivityLog::kKeyPropChangeType].asString();
611 
612   if (type == ActivityLog::kValuePropChangeTypeBool) {
613     if (!entry.isMember(ActivityLog::kKeyPropChangeValue)) {
614       Err("Can't parse prop change value");
615       return false;
616     }
617     prop_change.value =
618         static_cast<GesturesPropBool>(
619           entry[ActivityLog::kKeyPropChangeValue].asBool());
620   } else if (type == ActivityLog::kValuePropChangeTypeDouble) {
621     if (!entry.isMember(ActivityLog::kKeyPropChangeValue)) {
622       Err("Can't parse prop change value");
623       return false;
624     }
625     prop_change.value =
626         entry[ActivityLog::kKeyPropChangeValue].asDouble();
627   } else if (type == ActivityLog::kValuePropChangeTypeInt) {
628     if (!entry.isMember(ActivityLog::kKeyPropChangeValue)) {
629       Err("Can't parse prop change value");
630       return false;
631     }
632     prop_change.value =
633         entry[ActivityLog::kKeyPropChangeValue].asInt();
634   } else if (type == ActivityLog::kValuePropChangeTypeShort) {
635     if (!entry.isMember(ActivityLog::kKeyPropChangeValue)) {
636       Err("Can't parse prop change value");
637       return false;
638     }
639     prop_change.value =
640         static_cast<short>(
641           entry[ActivityLog::kKeyPropChangeValue].asInt());
642   } else {
643     Err("Unable to parse prop change type %s", type.c_str());
644     return false;
645   }
646   if (!entry.isMember(ActivityLog::kKeyPropChangeName)) {
647     Err("Unable to parse prop change name.");
648     return false;
649   }
650   const string* stored_name =
651       new string(entry[ActivityLog::kKeyPropChangeName].asString());  // alloc
652   // transfer ownership:
653   names_.push_back(std::shared_ptr<const string>(stored_name));
654   prop_change.name = stored_name->c_str();
655   log_.LogPropChange(prop_change);
656   return true;
657 }
658 
659 // Replay the log and verify the output in a strict way.
Replay(Interpreter * interpreter,MetricsProperties * mprops)660 void ActivityReplay::Replay(Interpreter* interpreter,
661                             MetricsProperties* mprops) {
662   interpreter->Initialize(&hwprops_, nullptr, mprops, this);
663 
664   stime_t last_timeout_req = -1.0;
665   // Use last_gs to save a copy of last gesture.
666   Gesture last_gs;
667   for (size_t i = 0; i < log_.size(); ++i) {
668     ActivityLog::Entry* entry = log_.GetEntry(i);
669     std::visit(
670       Visitor {
671         [&interpreter, &last_timeout_req](HardwareState hs) {
672           last_timeout_req = -1.0;
673           for (size_t i = 0; i < hs.finger_cnt; i++)
674             Log("Input Finger ID: %d", hs.fingers[i].tracking_id);
675           interpreter->SyncInterpret(hs, &last_timeout_req);
676         },
677         [&interpreter, &last_timeout_req]
678             (ActivityLog::TimerCallbackEntry now) {
679           last_timeout_req = -1.0;
680           interpreter->HandleTimer(now.timestamp, &last_timeout_req);
681         },
682         [&i, &last_timeout_req](ActivityLog::CallbackRequestEntry when) {
683           if (!DoubleEq(last_timeout_req, when.timestamp)) {
684             Err("Expected timeout request of %f, "
685                 "but log has %f (entry idx %zu)",
686                 last_timeout_req, when.timestamp, i);
687           }
688         },
689         [this](Gesture gesture) {
690           bool matched = false;
691           while (!consumed_gestures_.empty() && !matched) {
692             if (consumed_gestures_.front() == gesture) {
693               Log("Gesture matched:\n  Actual gesture: %s.\n"
694                   "Expected gesture: %s",
695                   consumed_gestures_.front().String().c_str(),
696                   gesture.String().c_str());
697               matched = true;
698             } else {
699               Log("Unmatched actual gesture: %s\n",
700                   consumed_gestures_.front().String().c_str());
701               ADD_FAILURE();
702             }
703             consumed_gestures_.pop_front();
704           }
705           if (!matched) {
706             Log("Missing logged gesture: %s", gesture.String().c_str());
707             ADD_FAILURE();
708           }
709         },
710         [this](ActivityLog::PropChangeEntry prop_change) {
711           ReplayPropChange(prop_change);
712         },
713         [](auto arg) {
714           Err("Unknown ActivityLog type");
715         }
716       }, entry->details);
717   }
718   while (!consumed_gestures_.empty()) {
719     Log("Unmatched actual gesture: %s\n",
720         consumed_gestures_.front().String().c_str());
721     ADD_FAILURE();
722     consumed_gestures_.pop_front();
723   }
724 }
725 
ConsumeGesture(const Gesture & gesture)726 void ActivityReplay::ConsumeGesture(const Gesture& gesture) {
727   consumed_gestures_.push_back(gesture);
728 }
729 
ReplayPropChange(const ActivityLog::PropChangeEntry & entry)730 bool ActivityReplay::ReplayPropChange(
731     const ActivityLog::PropChangeEntry& entry) {
732   if (!prop_reg_) {
733     Err("Missing prop registry.");
734     return false;
735   }
736   ::set<Property*> props = prop_reg_->props();
737   Property* prop = nullptr;
738   for (::set<Property*>::iterator it = props.begin(), e = props.end(); it != e;
739        ++it) {
740     prop = *it;
741     if (strcmp(prop->name(), entry.name.c_str()) == 0)
742       break;
743     prop = nullptr;
744   }
745   if (!prop) {
746     Err("Unable to find prop %s to set.", entry.name.c_str());
747     return false;
748   }
749   bool valid_property = true;
750   Json::Value value;
751   std::visit(
752     Visitor {
753       [&value](GesturesPropBool entry_value) {
754         value = Json::Value(static_cast<bool>(entry_value));
755       },
756       [&value](double entry_value) {
757         value = Json::Value(entry_value);
758       },
759       [&value](int entry_value) {
760         value = Json::Value(entry_value);
761       },
762       [&value](short entry_value) {
763         value = Json::Value(entry_value);
764       },
765       [&valid_property](auto arg) {
766         valid_property = false;
767         Err("Invalid property type");
768       }
769     }, entry.value);
770   if (valid_property) {
771     prop->SetValue(value);
772     prop->HandleGesturesPropWritten();
773   }
774   return valid_property;
775 }
776 
777 }  // namespace gestures
778