LookaheadInterpreter: Fix for interpolation locking queue.

If an interpolated event was generated and immediately overdue, the
time until it's due was negative, and this was interpreted as meaning
there's no input events to process anymore, and the input queue would
stop being processed.

BUG=chromium-os:22195
TEST=replayed deadlock log, saw lack of deadlock with fix; unittest

Change-Id: I99db42feb8e3310fee0084b697b02ba24a47bb17
diff --git a/include/lookahead_filter_interpreter.h b/include/lookahead_filter_interpreter.h
index 8ba5093..2771793 100644
--- a/include/lookahead_filter_interpreter.h
+++ b/include/lookahead_filter_interpreter.h
@@ -21,6 +21,7 @@
   FRIEND_TEST(LookaheadFilterInterpreterTest, CombineGesturesTest);
   FRIEND_TEST(LookaheadFilterInterpreterTest, InterpolateHwStateTest);
   FRIEND_TEST(LookaheadFilterInterpreterTest, InterpolateTest);
+  FRIEND_TEST(LookaheadFilterInterpreterTest, InterpolationOverdueTest);
   FRIEND_TEST(LookaheadFilterInterpreterTest, SimpleTest);
  public:
   LookaheadFilterInterpreter(PropRegistry* prop_reg, Interpreter* next);
diff --git a/src/lookahead_filter_interpreter.cc b/src/lookahead_filter_interpreter.cc
index e65591b..3300e20 100644
--- a/src/lookahead_filter_interpreter.cc
+++ b/src/lookahead_filter_interpreter.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <math.h>
+#include <values.h>
 
 using std::max;
 using std::min;
@@ -55,6 +56,9 @@
   }
   queue_.PushBack(node);
   AttemptInterpolation();
+  UpdateInterpreterDue(interpreter_due_ < 0.0 ?
+                       interpreter_due_ : interpreter_due_ + hwstate->timestamp,
+                       hwstate->timestamp, timeout);
   return HandleTimer(hwstate->timestamp, timeout);
 }
 
@@ -192,7 +196,9 @@
     stime_t new_interpreter_timeout,
     stime_t now,
     stime_t* timeout) {
-  stime_t next_hwstate_timeout = -1.0;
+  // The next hardware state may already be over due, thus having a negative
+  // timeout, so we use -DBL_MAX as the invalid value.
+  stime_t next_hwstate_timeout = -DBL_MAX;
   // Scan queue_ to find when next hwstate is due.
   for (QState* node = queue_.Begin(); node != queue_.End();
        node = node->next_) {
@@ -205,10 +211,10 @@
   interpreter_due_ = -1.0;
   if (new_interpreter_timeout >= 0.0 &&
       (new_interpreter_timeout < next_hwstate_timeout ||
-       next_hwstate_timeout < 0.0)) {
+       next_hwstate_timeout == -DBL_MAX)) {
     interpreter_due_ = new_interpreter_timeout + now;
     *timeout = new_interpreter_timeout;
-  } else if (next_hwstate_timeout >= 0.0) {
+  } else if (next_hwstate_timeout > -DBL_MAX) {
     *timeout = next_hwstate_timeout;
   }
 }
diff --git a/src/lookahead_filter_interpreter_unittest.cc b/src/lookahead_filter_interpreter_unittest.cc
index f1430f2..2c43dff 100644
--- a/src/lookahead_filter_interpreter_unittest.cc
+++ b/src/lookahead_filter_interpreter_unittest.cc
@@ -24,9 +24,13 @@
 class LookaheadFilterInterpreterTestInterpreter : public Interpreter {
  public:
   LookaheadFilterInterpreterTestInterpreter()
-      : set_hwprops_called_(false) {}
+      : timer_return_(-1.0), set_hwprops_called_(false) {}
 
   virtual Gesture* SyncInterpret(HardwareState* hwstate, stime_t* timeout) {
+    if (timer_return_ >= 0.0) {
+      *timeout = timer_return_;
+      timer_return_ = -1.0;
+    }
     if (return_values_.empty())
       return NULL;
     return_value_ = return_values_.front();
@@ -47,6 +51,7 @@
 
   Gesture return_value_;
   deque<Gesture> return_values_;
+  stime_t timer_return_;
   bool set_hwprops_called_;
 };
 
@@ -421,4 +426,66 @@
   }
 }
 
+TEST(LookaheadFilterInterpreterTest, InterpolationOverdueTest) {
+  LookaheadFilterInterpreterTestInterpreter* base_interpreter = NULL;
+  scoped_ptr<LookaheadFilterInterpreter> interpreter;
+
+  HardwareProperties initial_hwprops = {
+    0, 0, 10, 10,  // left, top, right, bottom
+    1,  // x res (pixels/mm)
+    1,  // y res (pixels/mm)
+    25, 25, 2, 5,  // scrn DPI X, Y, max fingers, max_touch,
+    1, 0, 0  // t5r2, semi, button pad
+  };
+
+  FingerState fs = {
+    // TM, Tm, WM, Wm, pr, orient, x, y, id
+    0, 0, 0, 0, 1, 0, 10, 1, 1
+  };
+  // These timestamps cause an interpolated event to be 1.492 at time 1.495,
+  // and so this tests that an overdue interpolated event is handled correctly.
+  HardwareState hs[] = {
+    // Expect movement to take
+    { 1.456, 0, 1, 1, &fs },
+    { 1.495, 0, 1, 1, &fs },
+  };
+
+  base_interpreter = new LookaheadFilterInterpreterTestInterpreter;
+  base_interpreter->timer_return_ = 0.700;
+  base_interpreter->return_values_.push_back(
+      Gesture(kGestureMove,
+              0,  // start time
+              1,  // end time
+              0,  // dx
+              1));  // dy
+  base_interpreter->return_values_.push_back(
+      Gesture(kGestureMove,
+              1,  // start time
+              2,  // end time
+              0,  // dx
+              2));  // dy
+  interpreter.reset(new LookaheadFilterInterpreter(NULL, base_interpreter));
+  interpreter->SetHardwareProperties(initial_hwprops);
+
+  stime_t timeout = -1.0;
+  Gesture* out = interpreter->SyncInterpret(&hs[0], &timeout);
+  EXPECT_EQ(reinterpret_cast<Gesture*>(NULL), out);
+  EXPECT_FLOAT_EQ(timeout, interpreter->delay_.val_);
+
+  stime_t now = hs[0].timestamp + timeout;
+  timeout = -1.0;
+  out = interpreter->HandleTimer(now, &timeout);
+  ASSERT_NE(reinterpret_cast<Gesture*>(NULL), out);
+  EXPECT_EQ(kGestureTypeMove, out->type);
+  EXPECT_EQ(1, out->details.move.dy);
+  EXPECT_DOUBLE_EQ(timeout, 0.700);
+
+  timeout = -1.0;
+  out = interpreter->SyncInterpret(&hs[1], &timeout);
+  ASSERT_NE(reinterpret_cast<Gesture*>(NULL), out);
+  EXPECT_EQ(kGestureTypeMove, out->type);
+  EXPECT_EQ(2, out->details.move.dy);
+  EXPECT_GE(timeout, 0.0);
+}
+
 }  // namespace gestures