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