Update metrics_daemon to use base/time.h instead of time_t directly.

Also, guard against time jumps in the active daily use metric collection.

BUG=none
TEST=unit tests; gmerge'd on the target device and inspected the logs.

Review URL: http://codereview.chromium.org/2576005
diff --git a/metrics/metrics_daemon.cc b/metrics/metrics_daemon.cc
index 6e01932..ecbea05 100644
--- a/metrics/metrics_daemon.cc
+++ b/metrics/metrics_daemon.cc
@@ -10,6 +10,10 @@
 #include <base/eintr_wrapper.h>
 #include <base/logging.h>
 
+using base::Time;
+using base::TimeDelta;
+using base::TimeTicks;
+
 #define SAFE_MESSAGE(e) (e.message ? e.message : "unknown error")
 #define DBUS_IFACE_CONNMAN_MANAGER "org.moblin.connman.Manager"
 #define DBUS_IFACE_POWER_MANAGER "org.chromium.Power.Manager"
@@ -25,7 +29,6 @@
 static const int kMinutesPerHour = 60;
 static const int kHoursPerDay = 24;
 static const int kMinutesPerDay = kHoursPerDay * kMinutesPerHour;
-static const int kSecondsPerDay = kMinutesPerDay * kSecondsPerMinute;
 
 // The daily use monitor is scheduled to a 1-minute interval after
 // initial user activity and then it's exponentially backed off to
@@ -152,8 +155,9 @@
 DBusHandlerResult MetricsDaemon::MessageFilter(DBusConnection* connection,
                                                DBusMessage* message,
                                                void* user_data) {
-  time_t now = time(NULL);
-  DLOG(INFO) << "message intercepted @ " << now;
+  Time now = Time::Now();
+  TimeTicks ticks = TimeTicks::Now();
+  DLOG(INFO) << "message intercepted @ " << now.ToInternalValue();
 
   int message_type = dbus_message_get_type(message);
   if (message_type != DBUS_MESSAGE_TYPE_SIGNAL) {
@@ -175,7 +179,7 @@
 
     char *state_name;
     dbus_message_iter_get_basic(&iter, &state_name);
-    daemon->NetStateChanged(state_name, now);
+    daemon->NetStateChanged(state_name, ticks);
   } else if (strcmp(interface, DBUS_IFACE_POWER_MANAGER) == 0) {
     CHECK(strcmp(dbus_message_get_member(message),
                  "PowerStateChanged") == 0);
@@ -205,7 +209,7 @@
   return DBUS_HANDLER_RESULT_HANDLED;
 }
 
-void MetricsDaemon::NetStateChanged(const char* state_name, time_t now) {
+void MetricsDaemon::NetStateChanged(const char* state_name, TimeTicks ticks) {
   DLOG(INFO) << "network state: " << state_name;
 
   NetworkState state = LookupNetworkState(state_name);
@@ -219,7 +223,8 @@
   if (state != kNetworkStateOnline &&
       network_state_ == kNetworkStateOnline &&
       power_state_ != kPowerStateMem) {
-    int online_time = static_cast<int>(now - network_state_last_);
+    TimeDelta since_online = ticks - network_state_last_;
+    int online_time = static_cast<int>(since_online.InSeconds());
     SendMetric(kMetricTimeToNetworkDropName, online_time,
                kMetricTimeToNetworkDropMin,
                kMetricTimeToNetworkDropMax,
@@ -227,7 +232,7 @@
   }
 
   network_state_ = state;
-  network_state_last_ = now;
+  network_state_last_ = ticks;
 }
 
 MetricsDaemon::NetworkState
@@ -241,7 +246,7 @@
   return kUnknownNetworkState;
 }
 
-void MetricsDaemon::PowerStateChanged(const char* state_name, time_t now) {
+void MetricsDaemon::PowerStateChanged(const char* state_name, Time now) {
   DLOG(INFO) << "power state: " << state_name;
   power_state_ = LookupPowerState(state_name);
 
@@ -260,8 +265,7 @@
   return kUnknownPowerState;
 }
 
-void MetricsDaemon::ScreenSaverStateChanged(const char* state_name,
-                                            time_t now) {
+void MetricsDaemon::ScreenSaverStateChanged(const char* state_name, Time now) {
   DLOG(INFO) << "screen-saver state: " << state_name;
   screensaver_state_ = LookupScreenSaverState(state_name);
   SetUserActiveState(screensaver_state_ == kScreenSaverStateUnlocked, now);
@@ -278,8 +282,7 @@
   return kUnknownScreenSaverState;
 }
 
-void MetricsDaemon::SessionStateChanged(const char* state_name,
-                                        time_t now) {
+void MetricsDaemon::SessionStateChanged(const char* state_name, Time now) {
   DLOG(INFO) << "user session state: " << state_name;
   session_state_ = LookupSessionState(state_name);
   SetUserActiveState(session_state_ == kSessionStateStarted, now);
@@ -296,13 +299,23 @@
   return kUnknownSessionState;
 }
 
-void MetricsDaemon::SetUserActiveState(bool active, time_t now) {
+void MetricsDaemon::SetUserActiveState(bool active, Time now) {
   DLOG(INFO) << "user: " << (active ? "active" : "inactive");
 
   // Calculates the seconds of active use since the last update and
-  // the day since Epoch, and logs the usage data.
-  int seconds = user_active_ ? (now - user_active_last_) : 0;
-  int day = now / kSecondsPerDay;
+  // the day since Epoch, and logs the usage data.  Guards against the
+  // time jumping back and forth due to the user changing it by
+  // discarding the new use time.
+  int seconds = 0;
+  if (user_active_ && now > user_active_last_) {
+    TimeDelta since_active = now - user_active_last_;
+    if (since_active < TimeDelta::FromSeconds(
+            kUseMonitorIntervalMax + kSecondsPerMinute)) {
+      seconds = static_cast<int>(since_active.InSeconds());
+    }
+  }
+  TimeDelta since_epoch = now - Time();
+  int day = since_epoch.InDays();
   LogDailyUseRecord(day, seconds);
 
   // Schedules a use monitor on inactive->active transitions and
@@ -388,7 +401,7 @@
 }
 
 bool MetricsDaemon::UseMonitor() {
-  SetUserActiveState(user_active_, time(NULL));
+  SetUserActiveState(user_active_, Time::Now());
 
   // If a new monitor source/instance is scheduled, returns false to
   // tell GLib to destroy this monitor source/instance. Returns true
diff --git a/metrics/metrics_daemon.h b/metrics/metrics_daemon.h
index ba9e13c..835aca3 100644
--- a/metrics/metrics_daemon.h
+++ b/metrics/metrics_daemon.h
@@ -7,11 +7,11 @@
 
 #include <dbus/dbus.h>
 #include <glib.h>
-#include <time.h>
 
 #include "metrics_library.h"
 
 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
+#include <base/time.h>
 
 class MetricsDaemon {
 
@@ -19,12 +19,10 @@
   MetricsDaemon()
       : daily_use_record_file_(NULL),
         network_state_(kUnknownNetworkState),
-        network_state_last_(0),
         power_state_(kUnknownPowerState),
         screensaver_state_(kUnknownScreenSaverState),
         session_state_(kUnknownSessionState),
         user_active_(false),
-        user_active_last_(0),
         daily_use_day_last_(0),
         usemon_interval_(0),
         usemon_source_(NULL) {}
@@ -56,6 +54,7 @@
   FRIEND_TEST(MetricsDaemonTest, SessionStateChanged);
   FRIEND_TEST(MetricsDaemonTest, SetUserActiveStateSendOnLogin);
   FRIEND_TEST(MetricsDaemonTest, SetUserActiveStateSendOnMonitor);
+  FRIEND_TEST(MetricsDaemonTest, SetUserActiveStateTimeJump);
 
   // The network states (see network_states.h).
   enum NetworkState {
@@ -131,25 +130,25 @@
                                          void* user_data);
 
   // Processes network state change.
-  void NetStateChanged(const char* state_name, time_t now);
+  void NetStateChanged(const char* state_name, base::TimeTicks ticks);
 
   // Given the state name, returns the state id.
   NetworkState LookupNetworkState(const char* state_name);
 
   // Processes power state change.
-  void PowerStateChanged(const char* state_name, time_t now);
+  void PowerStateChanged(const char* state_name, base::Time now);
 
   // Given the state name, returns the state id.
   PowerState LookupPowerState(const char* state_name);
 
   // Processes screen-saver state change.
-  void ScreenSaverStateChanged(const char* state_name, time_t now);
+  void ScreenSaverStateChanged(const char* state_name, base::Time now);
 
   // Given the state name, returns the state id.
   ScreenSaverState LookupScreenSaverState(const char* state_name);
 
   // Processes user session state change.
-  void SessionStateChanged(const char* state_name, time_t now);
+  void SessionStateChanged(const char* state_name, base::Time now);
 
   // Given the state name, returns the state id.
   SessionState LookupSessionState(const char* state_name);
@@ -158,7 +157,10 @@
   // since the last update. If the user has just become active,
   // reschedule the daily use monitor for more frequent updates --
   // this is followed by an exponential back-off (see UseMonitor).
-  void SetUserActiveState(bool active, time_t now);
+  // While in active use, this method should be called at intervals no
+  // longer than kUseMonitorIntervalMax otherwise new use time will be
+  // discarded.
+  void SetUserActiveState(bool active, base::Time now);
 
   // Updates the daily usage file, if necessary, by adding |seconds|
   // of active use to the |day| since Epoch. If there's usage data for
@@ -205,8 +207,10 @@
   // Current network state.
   NetworkState network_state_;
 
-  // Timestamps last network state update.
-  time_t network_state_last_;
+  // Timestamps last network state update.  This timestamp is used to
+  // sample the time from the network going online to going offline so
+  // TimeTicks ensures a monotonically increasing TimeDelta.
+  base::TimeTicks network_state_last_;
 
   // Current power state.
   PowerState power_state_;
@@ -221,10 +225,12 @@
   // started, screen is not locked.
   bool user_active_;
 
-  // Timestamps last user active update.
-  time_t user_active_last_;
+  // Timestamps last user active update.  Active use time is
+  // aggregated each day before sending to UMA so using time since the
+  // epoch as the timestamp.
+  base::Time user_active_last_;
 
-  // Last stored daily use day (since epoch).
+  // Last stored daily use day (since the epoch).
   int daily_use_day_last_;
 
   // Sleep period until the next daily usage aggregation performed by
diff --git a/metrics/metrics_daemon_test.cc b/metrics/metrics_daemon_test.cc
index 2edbeda..79be3dd 100644
--- a/metrics/metrics_daemon_test.cc
+++ b/metrics/metrics_daemon_test.cc
@@ -13,6 +13,8 @@
 #include <base/string_util.h>
 #include <gtest/gtest.h>
 
+using base::Time;
+using base::TimeTicks;
 using ::testing::Mock;
 using ::testing::Return;
 using ::testing::StrictMock;
@@ -22,13 +24,45 @@
 
 static const int kSecondsPerDay = 24 * 60 * 60;
 
+// This class allows a TimeTicks object to be initialized with seconds
+// (rather than microseconds) through the protected TimeTicks(int64)
+// constructor.
+class TestTicks : public TimeTicks {
+ public:
+  TestTicks(int64 seconds)
+      : TimeTicks(seconds * Time::kMicrosecondsPerSecond) {}
+};
+
+// Overloaded for test failure printing purposes.
+static std::ostream& operator<<(std::ostream& o, const TimeTicks& ticks) {
+  o << ticks.ToInternalValue() << "us";
+  return o;
+};
+
+// Overloaded for test failure printing purposes.
+static std::ostream& operator<<(std::ostream& o, const Time& time) {
+  o << time.ToInternalValue() << "us";
+  return o;
+};
+
 class MetricsDaemonTest : public testing::Test {
  protected:
   virtual void SetUp() {
     EXPECT_EQ(NULL, daemon_.daily_use_record_file_);
     daemon_.Init(true, &metrics_lib_);
+
+    // Tests constructor initialization. Switches to a test daily use
+    // record file.
     EXPECT_TRUE(NULL != daemon_.daily_use_record_file_);
     daemon_.daily_use_record_file_ = kTestDailyUseRecordFile;
+    EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
+    EXPECT_EQ(0, daemon_.daily_use_day_last_);
+    EXPECT_FALSE(daemon_.user_active_);
+    EXPECT_TRUE(daemon_.user_active_last_.is_null());
+    EXPECT_EQ(MetricsDaemon::kUnknownNetworkState, daemon_.network_state_);
+    EXPECT_TRUE(daemon_.network_state_last_.is_null());
+    EXPECT_EQ(MetricsDaemon::kUnknownPowerState, daemon_.power_state_);
+    EXPECT_EQ(MetricsDaemon::kUnknownSessionState, daemon_.session_state_);
 
     // The test fixture object will be used by the log message handler.
     daemon_test_ = this;
@@ -84,6 +118,10 @@
                  MetricsDaemon::kMetricTimeToNetworkDropBuckets);
   }
 
+  Time TestTime(int64 seconds) {
+    return Time::FromInternalValue(seconds * Time::kMicrosecondsPerSecond);
+  }
+
   // Asserts that the daily use record file contains the specified
   // contents.
   testing::AssertionResult AssertDailyUseRecord(const char* expr_day,
@@ -186,9 +224,6 @@
 }
 
 TEST_F(MetricsDaemonTest, LogDailyUseRecordOnLogin) {
-  EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
-
   daemon_.LogDailyUseRecord(/* day */ 5, /* seconds */ 120);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 5, /* seconds */ 120);
   EXPECT_EQ(5, daemon_.daily_use_day_last_);
@@ -208,9 +243,6 @@
 }
 
 TEST_F(MetricsDaemonTest, LogDailyUseRecordRoundDown) {
-  EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
-
   daemon_.LogDailyUseRecord(/* day */ 7, /* seconds */ 89);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 7, /* seconds */ 89);
   EXPECT_EQ(7, daemon_.daily_use_day_last_);
@@ -222,9 +254,6 @@
 }
 
 TEST_F(MetricsDaemonTest, LogDailyUseRecordRoundUp) {
-  EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
-
   daemon_.LogDailyUseRecord(/* day */ 6, /* seconds */ 0);
   EXPECT_EQ(6, daemon_.daily_use_day_last_);
 
@@ -334,125 +363,103 @@
 }
 
 TEST_F(MetricsDaemonTest, NetStateChangedSimpleDrop) {
-  EXPECT_EQ(MetricsDaemon::kUnknownNetworkState, daemon_.network_state_);
-  EXPECT_EQ(0, daemon_.network_state_last_);
-  EXPECT_EQ(MetricsDaemon::kUnknownPowerState, daemon_.power_state_);
-
-  daemon_.NetStateChanged("online", /* now */ 10);
+  daemon_.NetStateChanged("online", TestTicks(10));
   EXPECT_EQ(MetricsDaemon::kNetworkStateOnline, daemon_.network_state_);
-  EXPECT_EQ(10, daemon_.network_state_last_);
+  EXPECT_EQ(TestTicks(10), daemon_.network_state_last_);
 
   ExpectTimeToNetworkDropMetric(20);
-  daemon_.NetStateChanged("offline", /* now */ 30);
+  daemon_.NetStateChanged("offline", TestTicks(30));
   EXPECT_EQ(MetricsDaemon::kNetworkStateOffline, daemon_.network_state_);
-  EXPECT_EQ(30, daemon_.network_state_last_);
+  EXPECT_EQ(TestTicks(30), daemon_.network_state_last_);
 }
 
 TEST_F(MetricsDaemonTest, NetStateChangedSuspend) {
+  daemon_.NetStateChanged("offline", TestTicks(30));
+  EXPECT_EQ(MetricsDaemon::kNetworkStateOffline, daemon_.network_state_);
+  EXPECT_EQ(TestTicks(30), daemon_.network_state_last_);
+
+  daemon_.NetStateChanged("online", TestTicks(60));
+  EXPECT_EQ(MetricsDaemon::kNetworkStateOnline, daemon_.network_state_);
+  EXPECT_EQ(TestTicks(60), daemon_.network_state_last_);
+
+  daemon_.power_state_ = MetricsDaemon::kPowerStateMem;
+  daemon_.NetStateChanged("offline", TestTicks(85));
+  EXPECT_EQ(MetricsDaemon::kNetworkStateOffline, daemon_.network_state_);
+  EXPECT_EQ(TestTicks(85), daemon_.network_state_last_);
+
+  daemon_.NetStateChanged("somestate", TestTicks(90));
   EXPECT_EQ(MetricsDaemon::kUnknownNetworkState, daemon_.network_state_);
-  EXPECT_EQ(0, daemon_.network_state_last_);
-  EXPECT_EQ(MetricsDaemon::kUnknownPowerState, daemon_.power_state_);
+  EXPECT_EQ(TestTicks(90), daemon_.network_state_last_);
 
-  daemon_.NetStateChanged("offline", /* now */ 30);
+  daemon_.NetStateChanged("offline", TestTicks(95));
   EXPECT_EQ(MetricsDaemon::kNetworkStateOffline, daemon_.network_state_);
-  EXPECT_EQ(30, daemon_.network_state_last_);
+  EXPECT_EQ(TestTicks(95), daemon_.network_state_last_);
 
-  daemon_.NetStateChanged("online", /* now */ 60);
+  daemon_.power_state_ = MetricsDaemon::kPowerStateOn;
+  daemon_.NetStateChanged("online", TestTicks(105));
   EXPECT_EQ(MetricsDaemon::kNetworkStateOnline, daemon_.network_state_);
-  EXPECT_EQ(60, daemon_.network_state_last_);
-
-  daemon_.PowerStateChanged("mem", /* now */ 80);
-  EXPECT_EQ(MetricsDaemon::kPowerStateMem, daemon_.power_state_);
-  EXPECT_EQ(MetricsDaemon::kNetworkStateOnline, daemon_.network_state_);
-  EXPECT_EQ(60, daemon_.network_state_last_);
-
-  daemon_.NetStateChanged("offline", /* now */ 85);
-  EXPECT_EQ(MetricsDaemon::kNetworkStateOffline, daemon_.network_state_);
-  EXPECT_EQ(85, daemon_.network_state_last_);
-
-  daemon_.NetStateChanged("somestate", /* now */ 90);
-  EXPECT_EQ(MetricsDaemon::kUnknownNetworkState, daemon_.network_state_);
-  EXPECT_EQ(90, daemon_.network_state_last_);
-
-  daemon_.NetStateChanged("offline", /* now */ 95);
-  EXPECT_EQ(MetricsDaemon::kNetworkStateOffline, daemon_.network_state_);
-  EXPECT_EQ(95, daemon_.network_state_last_);
-
-  daemon_.PowerStateChanged("on", /* now */ 100);
-  EXPECT_EQ(MetricsDaemon::kPowerStateOn, daemon_.power_state_);
-  EXPECT_EQ(MetricsDaemon::kNetworkStateOffline, daemon_.network_state_);
-  EXPECT_EQ(95, daemon_.network_state_last_);
-
-  daemon_.NetStateChanged("online", /* now */ 105);
-  EXPECT_EQ(MetricsDaemon::kNetworkStateOnline, daemon_.network_state_);
-  EXPECT_EQ(105, daemon_.network_state_last_);
+  EXPECT_EQ(TestTicks(105), daemon_.network_state_last_);
 
   ExpectTimeToNetworkDropMetric(3);
-  daemon_.NetStateChanged("offline", /* now */ 108);
+  daemon_.NetStateChanged("offline", TestTicks(108));
   EXPECT_EQ(MetricsDaemon::kNetworkStateOffline, daemon_.network_state_);
-  EXPECT_EQ(108, daemon_.network_state_last_);
+  EXPECT_EQ(TestTicks(108), daemon_.network_state_last_);
 }
 
 TEST_F(MetricsDaemonTest, PowerStateChanged) {
-  EXPECT_EQ(MetricsDaemon::kUnknownPowerState, daemon_.power_state_);
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(0, daemon_.user_active_last_);
-  EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
-
-  daemon_.SetUserActiveState(/* active */ true, 7 * kSecondsPerDay + 15);
+  daemon_.SetUserActiveState(/* active */ true,
+                             TestTime(7 * kSecondsPerDay + 15));
   EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(7 * kSecondsPerDay + 15, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(7 * kSecondsPerDay + 15), daemon_.user_active_last_);
   EXPECT_EQ(7, daemon_.daily_use_day_last_);
   EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
-  daemon_.PowerStateChanged("mem", 7 * kSecondsPerDay + 45);
+  daemon_.PowerStateChanged("mem", TestTime(7 * kSecondsPerDay + 45));
   EXPECT_EQ(MetricsDaemon::kPowerStateMem, daemon_.power_state_);
   EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(7 * kSecondsPerDay + 45, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(7 * kSecondsPerDay + 45), daemon_.user_active_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 7, /* seconds */ 30);
 
-  daemon_.PowerStateChanged("on", 7 * kSecondsPerDay + 85);
+  daemon_.PowerStateChanged("on", TestTime(7 * kSecondsPerDay + 85));
   EXPECT_EQ(MetricsDaemon::kPowerStateOn, daemon_.power_state_);
   EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(7 * kSecondsPerDay + 45, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(7 * kSecondsPerDay + 45), daemon_.user_active_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 7, /* seconds */ 30);
 
-  daemon_.PowerStateChanged("otherstate", 7 * kSecondsPerDay + 185);
+  daemon_.PowerStateChanged("otherstate", TestTime(7 * kSecondsPerDay + 185));
   EXPECT_EQ(MetricsDaemon::kUnknownPowerState, daemon_.power_state_);
   EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(7 * kSecondsPerDay + 185, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(7 * kSecondsPerDay + 185), daemon_.user_active_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 7, /* seconds */ 30);
 }
 
 TEST_F(MetricsDaemonTest, ScreenSaverStateChanged) {
   EXPECT_EQ(MetricsDaemon::kUnknownScreenSaverState,
             daemon_.screensaver_state_);
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(0, daemon_.user_active_last_);
-  EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
-  daemon_.ScreenSaverStateChanged("locked", 5 * kSecondsPerDay + 10);
+  daemon_.ScreenSaverStateChanged("locked",
+                                  TestTime(5 * kSecondsPerDay + 10));
   EXPECT_EQ(MetricsDaemon::kScreenSaverStateLocked,
             daemon_.screensaver_state_);
   EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(5 * kSecondsPerDay + 10, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(5 * kSecondsPerDay + 10), daemon_.user_active_last_);
   EXPECT_EQ(5, daemon_.daily_use_day_last_);
   EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
-  daemon_.ScreenSaverStateChanged("unlocked", 5 * kSecondsPerDay + 100);
+  daemon_.ScreenSaverStateChanged("unlocked",
+                                  TestTime(5 * kSecondsPerDay + 100));
   EXPECT_EQ(MetricsDaemon::kScreenSaverStateUnlocked,
             daemon_.screensaver_state_);
   EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(5 * kSecondsPerDay + 100, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(5 * kSecondsPerDay + 100), daemon_.user_active_last_);
   EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
-  daemon_.ScreenSaverStateChanged("otherstate", 5 * kSecondsPerDay + 300);
+  daemon_.ScreenSaverStateChanged("otherstate",
+                                  TestTime(5 * kSecondsPerDay + 300));
   EXPECT_EQ(MetricsDaemon::kUnknownScreenSaverState,
             daemon_.screensaver_state_);
   EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(5 * kSecondsPerDay + 300, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(5 * kSecondsPerDay + 300), daemon_.user_active_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 5, /* seconds */ 200);
 }
 
@@ -463,100 +470,117 @@
 }
 
 TEST_F(MetricsDaemonTest, SessionStateChanged) {
-  EXPECT_EQ(MetricsDaemon::kUnknownSessionState, daemon_.session_state_);
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(0, daemon_.user_active_last_);
-  EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
-
-  daemon_.SessionStateChanged("started", 15 * kSecondsPerDay + 20);
+  daemon_.SessionStateChanged("started", TestTime(15 * kSecondsPerDay + 20));
   EXPECT_EQ(MetricsDaemon::kSessionStateStarted, daemon_.session_state_);
   EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(15 * kSecondsPerDay + 20, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(15 * kSecondsPerDay + 20), daemon_.user_active_last_);
   EXPECT_EQ(15, daemon_.daily_use_day_last_);
   EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
-  daemon_.SessionStateChanged("stopped", 15 * kSecondsPerDay + 150);
+  daemon_.SessionStateChanged("stopped", TestTime(15 * kSecondsPerDay + 150));
   EXPECT_EQ(MetricsDaemon::kSessionStateStopped, daemon_.session_state_);
   EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(15 * kSecondsPerDay + 150, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(15 * kSecondsPerDay + 150), daemon_.user_active_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 15, /* seconds */ 130);
 
-  daemon_.SessionStateChanged("otherstate", 15 * kSecondsPerDay + 300);
+  daemon_.SessionStateChanged("otherstate",
+                              TestTime(15 * kSecondsPerDay + 300));
   EXPECT_EQ(MetricsDaemon::kUnknownSessionState, daemon_.session_state_);
   EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(15 * kSecondsPerDay + 300, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(15 * kSecondsPerDay + 300), daemon_.user_active_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 15, /* seconds */ 130);
 }
 
 TEST_F(MetricsDaemonTest, SetUserActiveStateSendOnLogin) {
+  daemon_.SetUserActiveState(/* active */ false,
+                             TestTime(5 * kSecondsPerDay + 10));
   EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(0, daemon_.user_active_last_);
-  EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
-
-  daemon_.SetUserActiveState(/* active */ false, 5 * kSecondsPerDay + 10);
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(5 * kSecondsPerDay + 10, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(5 * kSecondsPerDay + 10), daemon_.user_active_last_);
   EXPECT_EQ(5, daemon_.daily_use_day_last_);
   EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
-  daemon_.SetUserActiveState(/* active */ true, 6 * kSecondsPerDay + 20);
+  daemon_.SetUserActiveState(/* active */ true,
+                             TestTime(6 * kSecondsPerDay + 20));
   EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(6 * kSecondsPerDay + 20, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(6 * kSecondsPerDay + 20), daemon_.user_active_last_);
   EXPECT_EQ(6, daemon_.daily_use_day_last_);
   EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
-  daemon_.SetUserActiveState(/* active */ true, 6 * kSecondsPerDay + 120);
+  daemon_.SetUserActiveState(/* active */ true,
+                             TestTime(6 * kSecondsPerDay + 120));
   EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(6 * kSecondsPerDay + 120, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(6 * kSecondsPerDay + 120), daemon_.user_active_last_);
   EXPECT_EQ(6, daemon_.daily_use_day_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 6, /* seconds */ 100);
 
-  daemon_.SetUserActiveState(/* active */ false, 6 * kSecondsPerDay + 220);
+  daemon_.SetUserActiveState(/* active */ false,
+                             TestTime(6 * kSecondsPerDay + 220));
   EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(6 * kSecondsPerDay + 220, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(6 * kSecondsPerDay + 220), daemon_.user_active_last_);
   EXPECT_EQ(6, daemon_.daily_use_day_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 6, /* seconds */ 200);
 
   ExpectDailyUseTimeMetric(/* sample */ 3);
-  daemon_.SetUserActiveState(/* active */ true, 8 * kSecondsPerDay - 300);
+  daemon_.SetUserActiveState(/* active */ true,
+                             TestTime(8 * kSecondsPerDay - 300));
   EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(8 * kSecondsPerDay - 300, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(8 * kSecondsPerDay - 300), daemon_.user_active_last_);
   EXPECT_EQ(7, daemon_.daily_use_day_last_);
   EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 }
 
 TEST_F(MetricsDaemonTest, SetUserActiveStateSendOnMonitor) {
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(0, daemon_.user_active_last_);
-  EXPECT_EQ(0, daemon_.daily_use_day_last_);
-  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
-
-  daemon_.SetUserActiveState(/* active */ true, 8 * kSecondsPerDay - 300);
+  daemon_.SetUserActiveState(/* active */ true,
+                             TestTime(8 * kSecondsPerDay - 300));
   EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(8 * kSecondsPerDay - 300, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(8 * kSecondsPerDay - 300), daemon_.user_active_last_);
   EXPECT_EQ(7, daemon_.daily_use_day_last_);
   EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 
-  daemon_.SetUserActiveState(/* active */ false, 8 * kSecondsPerDay + 300);
+  daemon_.SetUserActiveState(/* active */ false,
+                             TestTime(8 * kSecondsPerDay + 300));
   EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(8 * kSecondsPerDay + 300, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(8 * kSecondsPerDay + 300), daemon_.user_active_last_);
   EXPECT_EQ(8, daemon_.daily_use_day_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 8, /* seconds */ 600);
 
-  daemon_.SetUserActiveState(/* active */ true, 9 * kSecondsPerDay - 400);
+  daemon_.SetUserActiveState(/* active */ true,
+                             TestTime(9 * kSecondsPerDay - 200));
   EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(9 * kSecondsPerDay - 400, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(9 * kSecondsPerDay - 200), daemon_.user_active_last_);
   EXPECT_EQ(8, daemon_.daily_use_day_last_);
   EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 8, /* seconds */ 600);
 
   ExpectDailyUseTimeMetric(/* sample */ 10);
-  daemon_.SetUserActiveState(/* active */ true, 9 * kSecondsPerDay + 400);
+  daemon_.SetUserActiveState(/* active */ true,
+                             TestTime(9 * kSecondsPerDay + 200));
   EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(9 * kSecondsPerDay + 400, daemon_.user_active_last_);
+  EXPECT_EQ(TestTime(9 * kSecondsPerDay + 200), daemon_.user_active_last_);
   EXPECT_EQ(9, daemon_.daily_use_day_last_);
-  EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 9, /* seconds */ 800);
+  EXPECT_PRED_FORMAT2(AssertDailyUseRecord, /* day */ 9, /* seconds */ 400);
+}
+
+TEST_F(MetricsDaemonTest, SetUserActiveStateTimeJump) {
+  daemon_.SetUserActiveState(/* active */ true,
+                             TestTime(10 * kSecondsPerDay + 500));
+  EXPECT_TRUE(daemon_.user_active_);
+  EXPECT_EQ(TestTime(10 * kSecondsPerDay + 500), daemon_.user_active_last_);
+  EXPECT_EQ(10, daemon_.daily_use_day_last_);
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
+
+  daemon_.SetUserActiveState(/* active */ true,
+                             TestTime(10 * kSecondsPerDay + 300));
+  EXPECT_TRUE(daemon_.user_active_);
+  EXPECT_EQ(TestTime(10 * kSecondsPerDay + 300), daemon_.user_active_last_);
+  EXPECT_EQ(10, daemon_.daily_use_day_last_);
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
+
+  daemon_.SetUserActiveState(/* active */ true,
+                             TestTime(10 * kSecondsPerDay + 1000));
+  EXPECT_TRUE(daemon_.user_active_);
+  EXPECT_EQ(TestTime(10 * kSecondsPerDay + 1000), daemon_.user_active_last_);
+  EXPECT_EQ(10, daemon_.daily_use_day_last_);
+  EXPECT_TRUE(AssertNoOrEmptyUseRecordFile());
 }
 
 int main(int argc, char **argv) {