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