xref: /aosp_15_r20/external/libchrome-gestures/src/activity_replay.cc (revision aed3e5085e770be5b69ce25295ecf6ddf906af95)
1 // Copyright 2011 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "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::kKeyHardwarePropOrientationMinimum,
172            isDouble, asDouble, props.orientation_minimum, float, false);
173   PARSE_HP(obj, ActivityLog::kKeyHardwarePropOrientationMaximum,
174            isDouble, asDouble, props.orientation_maximum, float, false);
175   PARSE_HP(obj, ActivityLog::kKeyHardwarePropMaxFingerCount, isInt, asUInt,
176            props.max_finger_cnt, unsigned short, true);
177   PARSE_HP(obj, ActivityLog::kKeyHardwarePropMaxTouchCount, isInt, asUInt,
178            props.max_touch_cnt, unsigned short, true);
179   PARSE_HP(obj, ActivityLog::kKeyHardwarePropSupportsT5R2, isBool, asBool,
180            props.supports_t5r2, bool, true);
181   PARSE_HP(obj, ActivityLog::kKeyHardwarePropSemiMt,isBool, asBool,
182            props.support_semi_mt, bool, true);
183   PARSE_HP(obj, ActivityLog::kKeyHardwarePropIsButtonPad,isBool, asBool,
184            props.is_button_pad, bool, true);
185   PARSE_HP(obj, ActivityLog::kKeyHardwarePropHasWheel,isBool, asBool,
186            props.has_wheel, bool, true);
187   *out_props = props;
188   return true;
189 }
190 
191 #undef PARSE_HP
192 
ParseEntry(const Json::Value & entry)193 bool ActivityReplay::ParseEntry(const Json::Value& entry) {
194   if (!entry.isMember(ActivityLog::kKeyType) ||
195       entry[ActivityLog::kKeyType].type() != Json::stringValue) {
196     Err("Can't get entry type.");
197     return false;
198   }
199   string type = entry[ActivityLog::kKeyType].asString();
200   if (type == ActivityLog::kKeyHardwareState)
201     return ParseHardwareState(entry);
202   if (type == ActivityLog::kKeyTimerCallback)
203     return ParseTimerCallback(entry);
204   if (type == ActivityLog::kKeyCallbackRequest)
205     return ParseCallbackRequest(entry);
206   if (type == ActivityLog::kKeyGesture)
207     return ParseGesture(entry);
208   if (type == ActivityLog::kKeyPropChange)
209     return ParsePropChange(entry);
210   Err("Unknown entry type");
211   return false;
212 }
213 
ParseHardwareState(const Json::Value & entry)214 bool ActivityReplay::ParseHardwareState(const Json::Value& entry) {
215   HardwareState hs = HardwareState();
216   if (!entry.isMember(ActivityLog::kKeyHardwareStateButtonsDown)) {
217     Err("Unable to parse hardware state buttons down");
218     return false;
219   }
220   hs.buttons_down = entry[ActivityLog::kKeyHardwareStateButtonsDown].asUInt();
221   if (!entry.isMember(ActivityLog::kKeyHardwareStateTouchCnt)) {
222     Err("Unable to parse hardware state touch count");
223     return false;
224   }
225   hs.touch_cnt = entry[ActivityLog::kKeyHardwareStateTouchCnt].asUInt();
226   if (!entry.isMember(ActivityLog::kKeyHardwareStateTimestamp)) {
227     Err("Unable to parse hardware state timestamp");
228     return false;
229   }
230   hs.timestamp = entry[ActivityLog::kKeyHardwareStateTimestamp].asDouble();
231   if (!entry.isMember(ActivityLog::kKeyHardwareStateFingers)) {
232     Err("Unable to parse hardware state fingers");
233     return false;
234   }
235   Json::Value fingers = entry[ActivityLog::kKeyHardwareStateFingers];
236   // Sanity check
237   const size_t kMaxFingers = 30;
238   if (fingers.size() > kMaxFingers) {
239     Err("Too many fingers in hardware state");
240     return false;
241   }
242   FingerState fs[kMaxFingers];
243   for (size_t i = 0; i < fingers.size(); ++i) {
244     if (!fingers.isValidIndex(i)) {
245       Err("Invalid entry at index %zu", i);
246       return false;
247     }
248     const Json::Value& finger_state = fingers[static_cast<int>(i)];
249     if (!ParseFingerState(finger_state, &fs[i]))
250       return false;
251   }
252   hs.fingers = fs;
253   hs.finger_cnt = fingers.size();
254   // There may not have rel_ entries for old logs
255   if (entry.isMember(ActivityLog::kKeyHardwareStateRelX)) {
256     hs.rel_x = entry[ActivityLog::kKeyHardwareStateRelX].asDouble();
257     if (!entry.isMember(ActivityLog::kKeyHardwareStateRelY)) {
258       Err("Unable to parse hardware state rel_y");
259       return false;
260     }
261     hs.rel_x = entry[ActivityLog::kKeyHardwareStateRelY].asDouble();
262     if (!entry.isMember(ActivityLog::kKeyHardwareStateRelWheel)) {
263       Err("Unable to parse hardware state rel_wheel");
264       return false;
265     }
266     hs.rel_wheel = entry[ActivityLog::kKeyHardwareStateRelWheel].asDouble();
267     if (!entry.isMember(ActivityLog::kKeyHardwareStateRelHWheel)) {
268       Err("Unable to parse hardware state rel_hwheel");
269       return false;
270     }
271     hs.rel_hwheel = entry[ActivityLog::kKeyHardwareStateRelHWheel].asDouble();
272   }
273   log_.LogHardwareState(hs);
274   return true;
275 }
276 
ParseFingerState(const Json::Value & entry,FingerState * out_fs)277 bool ActivityReplay::ParseFingerState(const Json::Value& entry,
278                                       FingerState* out_fs) {
279   if (!entry.isMember(ActivityLog::kKeyFingerStateTouchMajor)) {
280     Err("can't parse finger's touch major");
281     return false;
282   }
283   out_fs->touch_major =
284       entry[ActivityLog::kKeyFingerStateTouchMajor].asDouble();
285   if (!entry.isMember(ActivityLog::kKeyFingerStateTouchMinor)) {
286     Err("can't parse finger's touch minor");
287     return false;
288   }
289   out_fs->touch_minor =
290       entry[ActivityLog::kKeyFingerStateTouchMinor].asDouble();
291   if (!entry.isMember(ActivityLog::kKeyFingerStateWidthMajor)) {
292     Err("can't parse finger's width major");
293     return false;
294   }
295   out_fs->width_major =
296       entry[ActivityLog::kKeyFingerStateWidthMajor].asDouble();
297   if (!entry.isMember(ActivityLog::kKeyFingerStateWidthMinor)) {
298     Err("can't parse finger's width minor");
299     return false;
300   }
301   out_fs->width_minor =
302       entry[ActivityLog::kKeyFingerStateWidthMinor].asDouble();
303   if (!entry.isMember(ActivityLog::kKeyFingerStatePressure)) {
304     Err("can't parse finger's pressure");
305     return false;
306   }
307   out_fs->pressure = entry[ActivityLog::kKeyFingerStatePressure].asDouble();
308   if (!entry.isMember(ActivityLog::kKeyFingerStateOrientation)) {
309     Err("can't parse finger's orientation");
310     return false;
311   }
312   out_fs->orientation =
313       entry[ActivityLog::kKeyFingerStateOrientation].asDouble();
314   if (!entry.isMember(ActivityLog::kKeyFingerStatePositionX)) {
315     Err("can't parse finger's position x");
316     return false;
317   }
318   out_fs->position_x = entry[ActivityLog::kKeyFingerStatePositionX].asDouble();
319   if (!entry.isMember(ActivityLog::kKeyFingerStatePositionY)) {
320     Err("can't parse finger's position y");
321     return false;
322   }
323   out_fs->position_y = entry[ActivityLog::kKeyFingerStatePositionY].asDouble();
324   if (!entry.isMember(ActivityLog::kKeyFingerStateTrackingId)) {
325     Err("can't parse finger's tracking id");
326     return false;
327   }
328   out_fs->tracking_id = entry[ActivityLog::kKeyFingerStateTrackingId].asInt();
329   if (!entry.isMember(ActivityLog::kKeyFingerStateFlags))
330     Err("can't parse finger's flags; continuing.");
331   out_fs->flags = entry[ActivityLog::kKeyFingerStateFlags].asUInt();
332   return true;
333 }
334 
ParseTimerCallback(const Json::Value & entry)335 bool ActivityReplay::ParseTimerCallback(const Json::Value& entry) {
336   if (!entry.isMember(ActivityLog::kKeyTimerNow)) {
337     Err("can't parse timercallback");
338     return false;
339   }
340   log_.LogTimerCallback(entry[ActivityLog::kKeyTimerNow].asDouble());
341   return true;
342 }
343 
ParseCallbackRequest(const Json::Value & entry)344 bool ActivityReplay::ParseCallbackRequest(const Json::Value& entry) {
345   if (!entry.isMember(ActivityLog::kKeyCallbackRequestWhen)) {
346     Err("can't parse callback request");
347     return false;
348   }
349   log_.LogCallbackRequest(
350       entry[ActivityLog::kKeyCallbackRequestWhen].asDouble());
351   return true;
352 }
353 
ParseGesture(const Json::Value & entry)354 bool ActivityReplay::ParseGesture(const Json::Value& entry) {
355   if (!entry.isMember(ActivityLog::kKeyGestureType)) {
356     Err("can't parse gesture type");
357     return false;
358   }
359   string gesture_type = entry[ActivityLog::kKeyGestureType].asString();
360   Gesture gs;
361 
362   if (!entry.isMember(ActivityLog::kKeyGestureStartTime)) {
363     Err("Failed to parse gesture start time");
364     return false;
365   }
366   gs.start_time = entry[ActivityLog::kKeyGestureStartTime].asDouble();
367   if (!entry.isMember(ActivityLog::kKeyGestureEndTime)) {
368     Err("Failed to parse gesture end time");
369     return false;
370   }
371   gs.end_time = entry[ActivityLog::kKeyGestureEndTime].asDouble();
372 
373   if (gesture_type == ActivityLog::kValueGestureTypeContactInitiated) {
374     gs.type = kGestureTypeContactInitiated;
375   } else if (gesture_type == ActivityLog::kValueGestureTypeMove) {
376     if (!ParseGestureMove(entry, &gs))
377       return false;
378   } else if (gesture_type == ActivityLog::kValueGestureTypeScroll) {
379     if (!ParseGestureScroll(entry, &gs))
380       return false;
381   } else if (gesture_type == ActivityLog::kValueGestureTypeSwipe) {
382     if (!ParseGestureSwipe(entry, &gs))
383       return false;
384   } else if (gesture_type == ActivityLog::kValueGestureTypeSwipeLift) {
385     if (!ParseGestureSwipeLift(entry, &gs))
386       return false;
387   } else if (gesture_type == ActivityLog::kValueGestureTypePinch) {
388     if (!ParseGesturePinch(entry, &gs))
389       return false;
390   } else if (gesture_type == ActivityLog::kValueGestureTypeButtonsChange) {
391     if (!ParseGestureButtonsChange(entry, &gs))
392       return false;
393   } else if (gesture_type == ActivityLog::kValueGestureTypeFling) {
394     if (!ParseGestureFling(entry, &gs))
395       return false;
396   } else if (gesture_type == ActivityLog::kValueGestureTypeMetrics) {
397     if (!ParseGestureMetrics(entry, &gs))
398       return false;
399   } else {
400     gs.type = kGestureTypeNull;
401   }
402   log_.LogGesture(gs);
403   return true;
404 }
405 
ParseGestureMove(const Json::Value & entry,Gesture * out_gs)406 bool ActivityReplay::ParseGestureMove(const Json::Value& entry,
407                                       Gesture* out_gs) {
408   out_gs->type = kGestureTypeMove;
409   if (!entry.isMember(ActivityLog::kKeyGestureDX)) {
410     Err("can't parse move dx");
411     return false;
412   }
413   out_gs->details.move.dx = entry[ActivityLog::kKeyGestureDX].asDouble();
414   if (!entry.isMember(ActivityLog::kKeyGestureDY)) {
415     Err("can't parse move dy");
416     return false;
417   }
418   out_gs->details.move.dy = entry[ActivityLog::kKeyGestureDY].asDouble();
419   if (!entry.isMember(ActivityLog::kKeyGestureOrdinalDX)) {
420     Err("can't parse move ordinal_dx");
421     return false;
422   }
423   out_gs->details.move.ordinal_dx =
424       entry[ActivityLog::kKeyGestureOrdinalDX].asDouble();
425   if (!entry.isMember(ActivityLog::kKeyGestureOrdinalDY)) {
426     Err("can't parse move ordinal_dy");
427     return false;
428   }
429   out_gs->details.move.ordinal_dy =
430       entry[ActivityLog::kKeyGestureOrdinalDY].asDouble();
431   return true;
432 }
433 
ParseGestureScroll(const Json::Value & entry,Gesture * out_gs)434 bool ActivityReplay::ParseGestureScroll(const Json::Value& entry,
435                                         Gesture* out_gs) {
436   out_gs->type = kGestureTypeScroll;
437   if (!entry.isMember(ActivityLog::kKeyGestureDX)) {
438     Err("can't parse scroll dx");
439     return false;
440   }
441   out_gs->details.scroll.dx =
442       entry[ActivityLog::kKeyGestureDX].asDouble();
443   if (!entry.isMember(ActivityLog::kKeyGestureDY)) {
444     Err("can't parse scroll dy");
445     return false;
446   }
447   out_gs->details.scroll.dy =
448       entry[ActivityLog::kKeyGestureDY].asDouble();
449   if (!entry.isMember(ActivityLog::kKeyGestureOrdinalDX)) {
450     Err("can't parse scroll ordinal_dx");
451     return false;
452   }
453   out_gs->details.scroll.ordinal_dx =
454       entry[ActivityLog::kKeyGestureOrdinalDX].asDouble();
455   if (!entry.isMember(ActivityLog::kKeyGestureOrdinalDY)) {
456     Err("can't parse scroll ordinal_dy");
457     return false;
458   }
459   out_gs->details.scroll.ordinal_dy =
460       entry[ActivityLog::kKeyGestureOrdinalDY].asDouble();
461   return true;
462 }
463 
ParseGestureSwipe(const Json::Value & entry,Gesture * out_gs)464 bool ActivityReplay::ParseGestureSwipe(const Json::Value& entry,
465                                        Gesture* out_gs) {
466   out_gs->type = kGestureTypeSwipe;
467   if (!entry.isMember(ActivityLog::kKeyGestureDX)) {
468     Err("can't parse swipe dx");
469     return false;
470   }
471   out_gs->details.swipe.dx = entry[ActivityLog::kKeyGestureDX].asDouble();
472   if (!entry.isMember(ActivityLog::kKeyGestureDY)) {
473     Err("can't parse swipe dy");
474     return false;
475   }
476   out_gs->details.swipe.dy = entry[ActivityLog::kKeyGestureDY].asDouble();
477   if (!entry.isMember(ActivityLog::kKeyGestureOrdinalDX)) {
478     Err("can't parse swipe ordinal_dx");
479     return false;
480   }
481   out_gs->details.swipe.ordinal_dx =
482       entry[ActivityLog::kKeyGestureOrdinalDX].asDouble();
483   if (!entry.isMember(ActivityLog::kKeyGestureOrdinalDY)) {
484     Err("can't parse swipe ordinal_dy");
485     return false;
486   }
487   out_gs->details.swipe.ordinal_dy =
488       entry[ActivityLog::kKeyGestureOrdinalDY].asDouble();
489   return true;
490 }
491 
ParseGestureSwipeLift(const Json::Value & entry,Gesture * out_gs)492 bool ActivityReplay::ParseGestureSwipeLift(const Json::Value& entry,
493                                            Gesture* out_gs) {
494   out_gs->type = kGestureTypeSwipeLift;
495   return true;
496 }
497 
ParseGesturePinch(const Json::Value & entry,Gesture * out_gs)498 bool ActivityReplay::ParseGesturePinch(const Json::Value& entry,
499                                        Gesture* out_gs) {
500   out_gs->type = kGestureTypePinch;
501   if (!entry.isMember(ActivityLog::kKeyGesturePinchDZ)) {
502     Err("can't parse pinch dz");
503     return false;
504   }
505   out_gs->details.pinch.dz = entry[ActivityLog::kKeyGesturePinchDZ].asDouble();
506   if (!entry.isMember(ActivityLog::kKeyGesturePinchOrdinalDZ)) {
507     Err("can't parse pinch ordinal_dz");
508     return false;
509   }
510   out_gs->details.pinch.ordinal_dz =
511       entry[ActivityLog::kKeyGesturePinchOrdinalDZ].asDouble();
512   if (!entry.isMember(ActivityLog::kKeyGesturePinchZoomState)) {
513     Err("can't parse pinch zoom_state");
514     return false;
515   }
516   out_gs->details.pinch.zoom_state =
517       entry[ActivityLog::kKeyGesturePinchZoomState].asInt();
518   return true;
519 }
520 
ParseGestureButtonsChange(const Json::Value & entry,Gesture * out_gs)521 bool ActivityReplay::ParseGestureButtonsChange(const Json::Value& entry,
522                                                Gesture* out_gs) {
523   out_gs->type = kGestureTypeButtonsChange;
524   if (!entry.isMember(ActivityLog::kKeyGestureButtonsChangeDown)) {
525     Err("can't parse buttons down");
526     return false;
527   }
528   out_gs->details.buttons.down =
529       entry[ActivityLog::kKeyGestureButtonsChangeDown].asUInt();
530   if (!entry.isMember(ActivityLog::kKeyGestureButtonsChangeUp)) {
531     Err("can't parse buttons up");
532     return false;
533   }
534   out_gs->details.buttons.up =
535       entry[ActivityLog::kKeyGestureButtonsChangeUp].asUInt();
536   return true;
537 }
538 
ParseGestureFling(const Json::Value & entry,Gesture * out_gs)539 bool ActivityReplay::ParseGestureFling(const Json::Value& entry,
540                                        Gesture* out_gs) {
541   out_gs->type = kGestureTypeFling;
542   if (!entry.isMember(ActivityLog::kKeyGestureFlingVX)) {
543     Err("can't parse fling vx");
544     return false;
545   }
546   out_gs->details.fling.vx = entry[ActivityLog::kKeyGestureFlingVX].asDouble();
547   if (!entry.isMember(ActivityLog::kKeyGestureFlingVY)) {
548     Err("can't parse fling vy");
549     return false;
550   }
551   out_gs->details.fling.vy = entry[ActivityLog::kKeyGestureFlingVY].asDouble();
552   if (!entry.isMember(ActivityLog::kKeyGestureFlingOrdinalVX)) {
553     Err("can't parse fling ordinal_vx");
554     return false;
555   }
556   out_gs->details.fling.ordinal_vx =
557       entry[ActivityLog::kKeyGestureFlingOrdinalVX].asDouble();
558   if (!entry.isMember(ActivityLog::kKeyGestureFlingOrdinalVY)) {
559     Err("can't parse fling ordinal_vy");
560     return false;
561   }
562   out_gs->details.fling.ordinal_vy =
563       entry[ActivityLog::kKeyGestureFlingOrdinalVY].asDouble();
564   if (!entry.isMember(ActivityLog::kKeyGestureFlingState)) {
565     Err("can't parse scroll is_scroll_begin");
566     return false;
567   }
568   out_gs->details.fling.fling_state =
569       entry[ActivityLog::kKeyGestureFlingState].asInt();
570   return true;
571 }
572 
ParseGestureMetrics(const Json::Value & entry,Gesture * out_gs)573 bool ActivityReplay::ParseGestureMetrics(const Json::Value& entry,
574                                        Gesture* out_gs) {
575   out_gs->type = kGestureTypeMetrics;
576   if (!entry.isMember(ActivityLog::kKeyGestureMetricsData1)) {
577     Err("can't parse metrics data 1");
578     return false;
579   }
580   out_gs->details.metrics.data[0] =
581       entry[ActivityLog::kKeyGestureMetricsData1].asDouble();
582   if (!entry.isMember(ActivityLog::kKeyGestureMetricsData2)) {
583     Err("can't parse metrics data 2");
584     return false;
585   }
586   out_gs->details.metrics.data[1] =
587       entry[ActivityLog::kKeyGestureMetricsData2].asDouble();
588   if (!entry.isMember(ActivityLog::kKeyGestureMetricsType)) {
589     Err("can't parse metrics type");
590     return false;
591   }
592   int type = entry[ActivityLog::kKeyGestureMetricsType].asInt();
593   if (type == 0) {
594     out_gs->details.metrics.type = kGestureMetricsTypeNoisyGround;
595     return true;
596   }
597   out_gs->details.metrics.type = kGestureMetricsTypeUnknown;
598   return true;
599 }
600 
ParsePropChange(const Json::Value & entry)601 bool ActivityReplay::ParsePropChange(const Json::Value& entry) {
602   ActivityLog::PropChangeEntry prop_change;
603   if (!entry.isMember(ActivityLog::kKeyPropChangeType)) {
604     Err("Can't get prop change type");
605     return false;
606   }
607   string type = entry[ActivityLog::kKeyPropChangeType].asString();
608 
609   if (type == ActivityLog::kValuePropChangeTypeBool) {
610     if (!entry.isMember(ActivityLog::kKeyPropChangeValue)) {
611       Err("Can't parse prop change value");
612       return false;
613     }
614     prop_change.value =
615         static_cast<GesturesPropBool>(
616           entry[ActivityLog::kKeyPropChangeValue].asBool());
617   } else if (type == ActivityLog::kValuePropChangeTypeDouble) {
618     if (!entry.isMember(ActivityLog::kKeyPropChangeValue)) {
619       Err("Can't parse prop change value");
620       return false;
621     }
622     prop_change.value =
623         entry[ActivityLog::kKeyPropChangeValue].asDouble();
624   } else if (type == ActivityLog::kValuePropChangeTypeInt) {
625     if (!entry.isMember(ActivityLog::kKeyPropChangeValue)) {
626       Err("Can't parse prop change value");
627       return false;
628     }
629     prop_change.value =
630         entry[ActivityLog::kKeyPropChangeValue].asInt();
631   } else if (type == ActivityLog::kValuePropChangeTypeShort) {
632     if (!entry.isMember(ActivityLog::kKeyPropChangeValue)) {
633       Err("Can't parse prop change value");
634       return false;
635     }
636     prop_change.value =
637         static_cast<short>(
638           entry[ActivityLog::kKeyPropChangeValue].asInt());
639   } else {
640     Err("Unable to parse prop change type %s", type.c_str());
641     return false;
642   }
643   if (!entry.isMember(ActivityLog::kKeyPropChangeName)) {
644     Err("Unable to parse prop change name.");
645     return false;
646   }
647   const string* stored_name =
648       new string(entry[ActivityLog::kKeyPropChangeName].asString());  // alloc
649   // transfer ownership:
650   names_.push_back(std::shared_ptr<const string>(stored_name));
651   prop_change.name = stored_name->c_str();
652   log_.LogPropChange(prop_change);
653   return true;
654 }
655 
656 // Replay the log and verify the output in a strict way.
Replay(Interpreter * interpreter,MetricsProperties * mprops)657 void ActivityReplay::Replay(Interpreter* interpreter,
658                             MetricsProperties* mprops) {
659   interpreter->Initialize(&hwprops_, nullptr, mprops, this);
660 
661   stime_t last_timeout_req = -1.0;
662   // Use last_gs to save a copy of last gesture.
663   Gesture last_gs;
664   for (size_t i = 0; i < log_.size(); ++i) {
665     ActivityLog::Entry* entry = log_.GetEntry(i);
666     std::visit(
667       Visitor {
668         [&interpreter, &last_timeout_req](HardwareState hs) {
669           last_timeout_req = -1.0;
670           for (size_t i = 0; i < hs.finger_cnt; i++)
671             Log("Input Finger ID: %d", hs.fingers[i].tracking_id);
672           interpreter->SyncInterpret(hs, &last_timeout_req);
673         },
674         [&interpreter, &last_timeout_req]
675             (ActivityLog::TimerCallbackEntry now) {
676           last_timeout_req = -1.0;
677           interpreter->HandleTimer(now.timestamp, &last_timeout_req);
678         },
679         [&i, &last_timeout_req](ActivityLog::CallbackRequestEntry when) {
680           if (!DoubleEq(last_timeout_req, when.timestamp)) {
681             Err("Expected timeout request of %f, "
682                 "but log has %f (entry idx %zu)",
683                 last_timeout_req, when.timestamp, i);
684           }
685         },
686         [this](Gesture gesture) {
687           bool matched = false;
688           while (!consumed_gestures_.empty() && !matched) {
689             if (consumed_gestures_.front() == gesture) {
690               Log("Gesture matched:\n  Actual gesture: %s.\n"
691                   "Expected gesture: %s",
692                   consumed_gestures_.front().String().c_str(),
693                   gesture.String().c_str());
694               matched = true;
695             } else {
696               Log("Unmatched actual gesture: %s\n",
697                   consumed_gestures_.front().String().c_str());
698               ADD_FAILURE();
699             }
700             consumed_gestures_.pop_front();
701           }
702           if (!matched) {
703             Log("Missing logged gesture: %s", gesture.String().c_str());
704             ADD_FAILURE();
705           }
706         },
707         [this](ActivityLog::PropChangeEntry prop_change) {
708           ReplayPropChange(prop_change);
709         },
710         [](auto arg) {
711           Err("Unknown ActivityLog type");
712         }
713       }, entry->details);
714   }
715   while (!consumed_gestures_.empty()) {
716     Log("Unmatched actual gesture: %s\n",
717         consumed_gestures_.front().String().c_str());
718     ADD_FAILURE();
719     consumed_gestures_.pop_front();
720   }
721 }
722 
ConsumeGesture(const Gesture & gesture)723 void ActivityReplay::ConsumeGesture(const Gesture& gesture) {
724   consumed_gestures_.push_back(gesture);
725 }
726 
ReplayPropChange(const ActivityLog::PropChangeEntry & entry)727 bool ActivityReplay::ReplayPropChange(
728     const ActivityLog::PropChangeEntry& entry) {
729   if (!prop_reg_) {
730     Err("Missing prop registry.");
731     return false;
732   }
733   ::set<Property*> props = prop_reg_->props();
734   Property* prop = nullptr;
735   for (::set<Property*>::iterator it = props.begin(), e = props.end(); it != e;
736        ++it) {
737     prop = *it;
738     if (strcmp(prop->name(), entry.name.c_str()) == 0)
739       break;
740     prop = nullptr;
741   }
742   if (!prop) {
743     Err("Unable to find prop %s to set.", entry.name.c_str());
744     return false;
745   }
746   bool valid_property = true;
747   Json::Value value;
748   std::visit(
749     Visitor {
750       [&value](GesturesPropBool entry_value) {
751         value = Json::Value(static_cast<bool>(entry_value));
752       },
753       [&value](double entry_value) {
754         value = Json::Value(entry_value);
755       },
756       [&value](int entry_value) {
757         value = Json::Value(entry_value);
758       },
759       [&value](short entry_value) {
760         value = Json::Value(entry_value);
761       },
762       [&valid_property](auto arg) {
763         valid_property = false;
764         Err("Invalid property type");
765       }
766     }, entry.value);
767   if (valid_property) {
768     prop->SetValue(value);
769     prop->HandleGesturesPropWritten();
770   }
771   return valid_property;
772 }
773 
774 }  // namespace gestures
775