metrics: Clean up user-active code.

Stop listening for the soon-to-deleted PowerStateChanged
D-Bus signal from powerd; the code that was listening for
it had some issues (there was no guarantee that it'd run
before the system suspended, and resumes weren't handled at
all).

Also remove the session-state- and screen-lock-handling
code; it provided an inaccurate view of user activity (what
if the user is listening to music with the screen locked or
if they don't have screen-locking enabled?).

Track uptime instead via a timer that fires every five
minutes.

BUG=chromium:359619
TEST=manual: ran metrics_daemon --nodaemon and watched the
     logs

Change-Id: I4ad74773daefa01afdea080d20001ff1944c2eee
Reviewed-on: https://chromium-review.googlesource.com/195491
Reviewed-by: Daniel Erat <derat@chromium.org>
Commit-Queue: Daniel Erat <derat@chromium.org>
Tested-by: Daniel Erat <derat@chromium.org>
diff --git a/metrics_daemon.cc b/metrics_daemon.cc
index 1f20699..47d74fa 100644
--- a/metrics_daemon.cc
+++ b/metrics_daemon.cc
@@ -32,33 +32,30 @@
 using std::string;
 using std::vector;
 
+namespace {
 
 #define SAFE_MESSAGE(e) (e.message ? e.message : "unknown error")
 
-static const char kCrashReporterInterface[] = "org.chromium.CrashReporter";
-static const char kCrashReporterUserCrashSignal[] = "UserCrash";
+const char kCrashReporterInterface[] = "org.chromium.CrashReporter";
+const char kCrashReporterUserCrashSignal[] = "UserCrash";
 
-static const int kSecondsPerMinute = 60;
-static const int kMinutesPerHour = 60;
-static const int kHoursPerDay = 24;
-static const int kMinutesPerDay = kHoursPerDay * kMinutesPerHour;
-static const int kSecondsPerDay = kSecondsPerMinute * kMinutesPerDay;
-static const int kDaysPerWeek = 7;
-static const int kSecondsPerWeek = kSecondsPerDay * kDaysPerWeek;
+const int kSecondsPerMinute = 60;
+const int kMinutesPerHour = 60;
+const int kHoursPerDay = 24;
+const int kMinutesPerDay = kHoursPerDay * kMinutesPerHour;
+const int kSecondsPerDay = kSecondsPerMinute * kMinutesPerDay;
+const int kDaysPerWeek = 7;
+const int kSecondsPerWeek = kSecondsPerDay * kDaysPerWeek;
 
-// The daily use monitor is scheduled to a 1-minute interval after
-// initial user activity and then it's exponentially backed off to
-// 10-minute intervals. Although not required, the back off is
-// implemented because the histogram buckets are spaced exponentially
-// anyway and to avoid too frequent metrics daemon process wake-ups
-// and file I/O.
-static const int kUseMonitorIntervalInit = 1 * kSecondsPerMinute;
-static const int kUseMonitorIntervalMax = 10 * kSecondsPerMinute;
+// Interval between calls to UpdateStats().
+const guint kUpdateStatsIntervalMs = 300000;
 
 const char kKernelCrashDetectedFile[] = "/var/run/kernel-crash-detected";
-static const char kUncleanShutdownDetectedFile[] =
+const char kUncleanShutdownDetectedFile[] =
     "/var/run/unclean-shutdown-detected";
 
+}  // namespace
+
 // disk stats metrics
 
 // The {Read,Write}Sectors numbers are in sectors/second.
@@ -114,18 +111,6 @@
 const char MetricsDaemon::kMetricScaledCpuFrequencyName[] =
     "Platform.CpuFrequencyThermalScaling";
 
-// static
-const char* MetricsDaemon::kPowerStates_[] = {
-#define STATE(name, capname) #name,
-#include "power_states.h"
-};
-
-// static
-const char* MetricsDaemon::kSessionStates_[] = {
-#define STATE(name, capname) #name,
-#include "session_states.h"
-};
-
 // Memory use stats collection intervals.  We collect some memory use interval
 // at these intervals after boot, and we stop collecting after the last one,
 // with the assumption that in most cases the memory use won't change much
@@ -139,11 +124,7 @@
 };
 
 MetricsDaemon::MetricsDaemon()
-    : power_state_(kUnknownPowerState),
-      session_state_(kUnknownSessionState),
-      user_active_(false),
-      usemon_interval_(0),
-      usemon_source_(NULL),
+    : update_stats_timeout_id_(-1),
       memuse_final_time_(0),
       memuse_interval_index_(0),
       read_sectors_(0),
@@ -155,6 +136,8 @@
       latest_cpu_use_ticks_(0) {}
 
 MetricsDaemon::~MetricsDaemon() {
+  if (update_stats_timeout_id_ > -1)
+    g_source_remove(update_stats_timeout_id_);
 }
 
 double MetricsDaemon::GetActiveTime() {
@@ -214,8 +197,7 @@
                          const string& diskstats_path,
                          const string& vmstats_path,
                          const string& scaling_max_freq_path,
-                         const string& cpuinfo_max_freq_path
-                         ) {
+                         const string& cpuinfo_max_freq_path) {
   testing_ = testing;
   DCHECK(metrics_lib != NULL);
   metrics_lib_ = metrics_lib;
@@ -291,16 +273,6 @@
       base::StringPrintf("type='signal',interface='%s',path='/',member='%s'",
                          kCrashReporterInterface,
                          kCrashReporterUserCrashSignal));
-  matches.push_back(
-      base::StringPrintf("type='signal',interface='%s',path='%s',member='%s'",
-                         power_manager::kPowerManagerInterface,
-                         power_manager::kPowerManagerServicePath,
-                         power_manager::kPowerStateChangedSignal));
-  matches.push_back(
-      base::StringPrintf("type='signal',sender='%s',interface='%s',path='%s'",
-                         login_manager::kSessionManagerServiceName,
-                         login_manager::kSessionManagerInterface,
-                         login_manager::kSessionManagerServicePath));
 
   // Registers D-Bus matches for the signals we would like to catch.
   for (vector<string>::const_iterator it = matches.begin();
@@ -316,6 +288,9 @@
   // the registered D-Bus matches is successful. The daemon is not
   // activated for D-Bus messages that don't match.
   CHECK(dbus_connection_add_filter(connection, MessageFilter, this, NULL));
+
+  update_stats_timeout_id_ =
+      g_timeout_add(kUpdateStatsIntervalMs, &HandleUpdateStatsTimeout, this);
 }
 
 void MetricsDaemon::Loop() {
@@ -327,9 +302,6 @@
 DBusHandlerResult MetricsDaemon::MessageFilter(DBusConnection* connection,
                                                DBusMessage* message,
                                                void* user_data) {
-  Time now = Time::Now();
-  DLOG(INFO) << "message intercepted @ " << now.ToInternalValue();
-
   int message_type = dbus_message_get_type(message);
   if (message_type != DBUS_MESSAGE_TYPE_SIGNAL) {
     DLOG(WARNING) << "unexpected message type " << message_type;
@@ -337,115 +309,29 @@
   }
 
   // Signal messages always have interfaces.
-  const char* interface = dbus_message_get_interface(message);
-  CHECK(interface != NULL);
+  const std::string interface(dbus_message_get_interface(message));
+  const std::string member(dbus_message_get_member(message));
+  DLOG(INFO) << "Got " << interface << "." << member << " D-Bus signal";
 
   MetricsDaemon* daemon = static_cast<MetricsDaemon*>(user_data);
 
   DBusMessageIter iter;
   dbus_message_iter_init(message, &iter);
-  if (strcmp(interface, kCrashReporterInterface) == 0) {
-    CHECK(strcmp(dbus_message_get_member(message),
-                 kCrashReporterUserCrashSignal) == 0);
+  if (interface == kCrashReporterInterface) {
+    CHECK_EQ(member, kCrashReporterUserCrashSignal);
     daemon->ProcessUserCrash();
-  } else if (strcmp(interface, power_manager::kPowerManagerInterface) == 0) {
-    CHECK(strcmp(dbus_message_get_member(message),
-                 power_manager::kPowerStateChangedSignal) == 0);
-    char* state_name;
-    dbus_message_iter_get_basic(&iter, &state_name);
-    daemon->PowerStateChanged(state_name, now);
-  } else if (strcmp(interface, login_manager::kSessionManagerInterface) == 0) {
-    const char* member = dbus_message_get_member(message);
-    if (strcmp(member, login_manager::kScreenIsLockedSignal) == 0) {
-      daemon->SetUserActiveState(false, now);
-    } else if (strcmp(member, login_manager::kScreenIsUnlockedSignal) == 0) {
-      daemon->SetUserActiveState(true, now);
-    } else if (strcmp(member, login_manager::kSessionStateChangedSignal) == 0) {
-      char* state_name;
-      dbus_message_iter_get_basic(&iter, &state_name);
-      daemon->SessionStateChanged(state_name, now);
-    }
   } else {
-    DLOG(WARNING) << "unexpected interface: " << interface;
+    // Ignore messages from the bus itself.
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
   }
 
   return DBUS_HANDLER_RESULT_HANDLED;
 }
 
-void MetricsDaemon::PowerStateChanged(const char* state_name, Time now) {
-  DLOG(INFO) << "power state: " << state_name;
-  power_state_ = LookupPowerState(state_name);
-
-  if (power_state_ != kPowerStateOn)
-    SetUserActiveState(false, now);
-}
-
-MetricsDaemon::PowerState
-MetricsDaemon::LookupPowerState(const char* state_name) {
-  for (int i = 0; i < kNumberPowerStates; i++) {
-    if (strcmp(state_name, kPowerStates_[i]) == 0) {
-      return static_cast<PowerState>(i);
-    }
-  }
-  DLOG(WARNING) << "unknown power state: " << state_name;
-  return kUnknownPowerState;
-}
-
-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);
-}
-
-MetricsDaemon::SessionState
-MetricsDaemon::LookupSessionState(const char* state_name) {
-  for (int i = 0; i < kNumberSessionStates; i++) {
-    if (strcmp(state_name, kSessionStates_[i]) == 0) {
-      return static_cast<SessionState>(i);
-    }
-  }
-  DLOG(WARNING) << "unknown user session state: " << state_name;
-  return kUnknownSessionState;
-}
-
-void MetricsDaemon::ReportStats(int64 active_use_seconds, Time now) {
-  TimeDelta since_epoch = now - Time::UnixEpoch();
-  int day = since_epoch.InDays();
-  int week = day / 7;
-
-  if (daily_cycle_->Get() == day) {
-    // We did today already.
-    return;
-  }
-  daily_cycle_->Set(day);
-
-  // Daily stats.
-  ReportDailyUse(active_use_seconds);
-  SendCrashFrequencySample(any_crashes_daily_count_);
-  SendCrashFrequencySample(user_crashes_daily_count_);
-  SendCrashFrequencySample(kernel_crashes_daily_count_);
-  SendCrashFrequencySample(unclean_shutdowns_daily_count_);
-  SendKernelCrashesCumulativeCountStats(active_use_seconds);
-
-  if (weekly_cycle_->Get() == week) {
-    // We did this week already.
-    return;
-  }
-  weekly_cycle_->Set(week);
-
-  // Weekly stats.
-  SendCrashFrequencySample(any_crashes_weekly_count_);
-  SendCrashFrequencySample(user_crashes_weekly_count_);
-  SendCrashFrequencySample(kernel_crashes_weekly_count_);
-  SendCrashFrequencySample(unclean_shutdowns_weekly_count_);
-}
-
 // One might argue that parts of this should go into
 // chromium/src/base/sys_info_chromeos.c instead, but put it here for now.
 
 TimeDelta MetricsDaemon::GetIncrementalCpuUse() {
-
   FilePath proc_stat_path = FilePath(kMetricsProcStatFileName);
   std::string proc_stat_string;
   if (!base::ReadFileToString(proc_stat_path, &proc_stat_string)) {
@@ -489,47 +375,9 @@
       diff * 1000 * 1000 / ticks_per_second_);
 }
 
-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.  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());
-    }
-  }
-  daily_use_->Add(seconds);
-  user_crash_interval_->Add(seconds);
-  kernel_crash_interval_->Add(seconds);
-
-  // Updates the CPU time accumulator.
-  version_cumulative_cpu_use_->Add(GetIncrementalCpuUse().InMilliseconds());
-
-  // Report daily and weekly stats as needed.
-  ReportStats(daily_use_->Get(), now);
-
-  // Schedules a use monitor on inactive->active transitions and
-  // unschedules it on active->inactive transitions.
-  if (!user_active_ && active)
-    ScheduleUseMonitor(kUseMonitorIntervalInit, /* backoff */ false);
-  else if (user_active_ && !active)
-    UnscheduleUseMonitor();
-
-  // Remembers the current active state and the time of the last
-  // activity update.
-  user_active_ = active;
-  user_active_last_ = now;
-}
-
 void MetricsDaemon::ProcessUserCrash() {
-  // Counts the active use time up to now.
-  SetUserActiveState(user_active_, Time::Now());
+  // Counts the active time up to now.
+  UpdateStats(TimeTicks::Now(), Time::Now());
 
   // Reports the active use time since the last crash and resets it.
   SendCrashIntervalSample(user_crash_interval_);
@@ -541,8 +389,8 @@
 }
 
 void MetricsDaemon::ProcessKernelCrash() {
-  // Counts the active use time up to now.
-  SetUserActiveState(user_active_, Time::Now());
+  // Counts the active time up to now.
+  UpdateStats(TimeTicks::Now(), Time::Now());
 
   // Reports the active use time since the last crash and resets it.
   SendCrashIntervalSample(kernel_crash_interval_);
@@ -556,8 +404,8 @@
 }
 
 void MetricsDaemon::ProcessUncleanShutdown() {
-  // Counts the active use time up to now.
-  SetUserActiveState(user_active_, Time::Now());
+  // Counts the active time up to now.
+  UpdateStats(TimeTicks::Now(), Time::Now());
 
   // Reports the active use time since the last crash and resets it.
   SendCrashIntervalSample(unclean_shutdown_interval_);
@@ -579,66 +427,6 @@
   return true;
 }
 
-// static
-gboolean MetricsDaemon::UseMonitorStatic(gpointer data) {
-  return static_cast<MetricsDaemon*>(data)->UseMonitor() ? TRUE : FALSE;
-}
-
-bool MetricsDaemon::UseMonitor() {
-  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
-  // otherwise to keep calling back this monitor.
-  return !ScheduleUseMonitor(usemon_interval_ * 2, /* backoff */ true);
-}
-
-bool MetricsDaemon::ScheduleUseMonitor(int interval, bool backoff)
-{
-  if (testing_)
-    return false;
-
-  // Caps the interval -- the bigger the interval, the more active use
-  // time will be potentially dropped on system shutdown.
-  if (interval > kUseMonitorIntervalMax)
-    interval = kUseMonitorIntervalMax;
-
-  if (backoff) {
-    // Back-off mode is used by the use monitor to reschedule itself
-    // with exponential back-off in time. This mode doesn't create a
-    // new timeout source if the new interval is the same as the old
-    // one. Also, if a new timeout source is created, the old one is
-    // not destroyed explicitly here -- it will be destroyed by GLib
-    // when the monitor returns FALSE (see UseMonitor and
-    // UseMonitorStatic).
-    if (interval == usemon_interval_)
-      return false;
-  } else {
-    UnscheduleUseMonitor();
-  }
-
-  // Schedules a new use monitor for |interval| seconds from now.
-  DLOG(INFO) << "scheduling use monitor in " << interval << " seconds";
-  usemon_source_ = g_timeout_source_new_seconds(interval);
-  g_source_set_callback(usemon_source_, UseMonitorStatic, this,
-                        NULL); // No destroy notification.
-  g_source_attach(usemon_source_,
-                  NULL); // Default context.
-  usemon_interval_ = interval;
-  return true;
-}
-
-void MetricsDaemon::UnscheduleUseMonitor() {
-  // If there's a use monitor scheduled already, destroys it.
-  if (usemon_source_ == NULL)
-    return;
-
-  DLOG(INFO) << "destroying use monitor";
-  g_source_destroy(usemon_source_);
-  usemon_source_ = NULL;
-  usemon_interval_ = 0;
-}
-
 void MetricsDaemon::StatsReporterInit() {
   DiskStatsReadStats(&read_sectors_, &write_sectors_);
   VmStatsReadStats(&vmstats_);
@@ -1212,3 +1000,40 @@
   LOG_IF(FATAL, nbuckets != max + 1) << "unsupported histogram scale";
   metrics_lib_->SendEnumToUMA(name, sample, max);
 }
+
+void MetricsDaemon::UpdateStats(TimeTicks now_ticks,
+                                Time now_wall_time) {
+  const int elapsed_seconds = (now_ticks - last_update_stats_time_).InSeconds();
+  daily_use_->Add(elapsed_seconds);
+  user_crash_interval_->Add(elapsed_seconds);
+  kernel_crash_interval_->Add(elapsed_seconds);
+  version_cumulative_cpu_use_->Add(GetIncrementalCpuUse().InMilliseconds());
+  last_update_stats_time_ = now_ticks;
+
+  const TimeDelta since_epoch = now_wall_time - Time::UnixEpoch();
+  const int day = since_epoch.InDays();
+  const int week = day / 7;
+
+  if (daily_cycle_->Get() != day) {
+    daily_cycle_->Set(day);
+    SendCrashFrequencySample(any_crashes_daily_count_);
+    SendCrashFrequencySample(user_crashes_daily_count_);
+    SendCrashFrequencySample(kernel_crashes_daily_count_);
+    SendCrashFrequencySample(unclean_shutdowns_daily_count_);
+    SendKernelCrashesCumulativeCountStats(daily_use_->Get());
+  }
+
+  if (weekly_cycle_->Get() != week) {
+    weekly_cycle_->Set(week);
+    SendCrashFrequencySample(any_crashes_weekly_count_);
+    SendCrashFrequencySample(user_crashes_weekly_count_);
+    SendCrashFrequencySample(kernel_crashes_weekly_count_);
+    SendCrashFrequencySample(unclean_shutdowns_weekly_count_);
+  }
+}
+
+// static
+gboolean MetricsDaemon::HandleUpdateStatsTimeout(gpointer data) {
+  static_cast<MetricsDaemon*>(data)->UpdateStats(TimeTicks::Now(), Time::Now());
+  return TRUE;
+}
diff --git a/metrics_daemon.h b/metrics_daemon.h
index de9fd74..929706a 100644
--- a/metrics_daemon.h
+++ b/metrics_daemon.h
@@ -43,12 +43,8 @@
   FRIEND_TEST(MetricsDaemonTest, ComputeEpochNoLast);
   FRIEND_TEST(MetricsDaemonTest, GetHistogramPath);
   FRIEND_TEST(MetricsDaemonTest, IsNewEpoch);
-  FRIEND_TEST(MetricsDaemonTest, LookupPowerState);
-  FRIEND_TEST(MetricsDaemonTest, LookupScreenSaverState);
-  FRIEND_TEST(MetricsDaemonTest, LookupSessionState);
   FRIEND_TEST(MetricsDaemonTest, MessageFilter);
   FRIEND_TEST(MetricsDaemonTest, ParseVmStats);
-  FRIEND_TEST(MetricsDaemonTest, PowerStateChanged);
   FRIEND_TEST(MetricsDaemonTest, ProcessKernelCrash);
   FRIEND_TEST(MetricsDaemonTest, ProcessMeminfo);
   FRIEND_TEST(MetricsDaemonTest, ProcessMeminfo2);
@@ -61,28 +57,8 @@
   FRIEND_TEST(MetricsDaemonTest, ReportKernelCrashInterval);
   FRIEND_TEST(MetricsDaemonTest, ReportUncleanShutdownInterval);
   FRIEND_TEST(MetricsDaemonTest, ReportUserCrashInterval);
-  FRIEND_TEST(MetricsDaemonTest, ScreenSaverStateChanged);
   FRIEND_TEST(MetricsDaemonTest, SendSample);
   FRIEND_TEST(MetricsDaemonTest, SendCpuThrottleMetrics);
-  FRIEND_TEST(MetricsDaemonTest, SessionStateChanged);
-  FRIEND_TEST(MetricsDaemonTest, SetUserActiveState);
-  FRIEND_TEST(MetricsDaemonTest, SetUserActiveStateTimeJump);
-
-  // The power states (see power_states.h).
-  enum PowerState {
-    kUnknownPowerState = -1, // Initial/unknown power state.
-#define STATE(name, capname) kPowerState ## capname,
-#include "power_states.h"
-    kNumberPowerStates
-  };
-
-  // The user session states (see session_states.h).
-  enum SessionState {
-    kUnknownSessionState = -1, // Initial/unknown user session state.
-#define STATE(name, capname) kSessionState ## capname,
-#include "session_states.h"
-    kNumberSessionStates
-  };
 
   // State for disk stats collector callback.
   enum StatsState {
@@ -148,12 +124,6 @@
   static const char kMetricsProcStatFileName[];
   static const int kMetricsProcStatFirstLineItemsCount;
 
-  // Array of power states.
-  static const char* kPowerStates_[kNumberPowerStates];
-
-  // Array of user session states.
-  static const char* kSessionStates_[kNumberSessionStates];
-
   // Returns the active time since boot (uptime minus sleep time) in seconds.
   double GetActiveTime();
 
@@ -165,27 +135,6 @@
                                          DBusMessage* message,
                                          void* user_data);
 
-  // Processes power state change.
-  void PowerStateChanged(const char* state_name, base::Time now);
-
-  // Given the state name, returns the state id.
-  PowerState LookupPowerState(const char* state_name);
-
-  // Processes user session state change.
-  void SessionStateChanged(const char* state_name, base::Time now);
-
-  // Given the state name, returns the state id.
-  SessionState LookupSessionState(const char* state_name);
-
-  // Updates the user-active state to |active| and logs the usage data
-  // 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).
-  // 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
   // day in the past in the usage file, that data is sent to UMA and
@@ -209,27 +158,6 @@
   // exists, so it must not be called more than once.
   bool CheckSystemCrash(const std::string& crash_file);
 
-  // Callbacks for the daily use monitor. The daily use monitor uses
-  // LogDailyUseRecord to aggregate current usage data and send it to
-  // UMA, if necessary. It also reschedules itself using an
-  // exponentially bigger interval (up to a certain maximum) -- so
-  // usage is monitored less frequently with longer active use.
-  static gboolean UseMonitorStatic(gpointer data);
-  bool UseMonitor();
-
-  // Schedules or reschedules a daily use monitor for |interval|
-  // seconds from now. |backoff| mode is used by the use monitor to
-  // reschedule itself. If there's a monitor scheduled already and
-  // |backoff| is false, unschedules it first. Doesn't schedule a
-  // monitor for more than kUseMonitorIntervalMax seconds in the
-  // future (see metrics_daemon.cc). Returns true if a new use monitor
-  // was scheduled, false otherwise (note that if |backoff| is false a
-  // new use monitor will always be scheduled).
-  bool ScheduleUseMonitor(int interval, bool backoff);
-
-  // Unschedules a scheduled use monitor, if any.
-  void UnscheduleUseMonitor();
-
   // Report daily use through UMA.
   void ReportDailyUse(int use_seconds);
 
@@ -327,13 +255,17 @@
   // Reads an integer CPU frequency value from sysfs.
   bool ReadFreqToInt(const std::string& sysfs_file_name, int* value);
 
-  // Report UMA stats when cycles (daily or weekly) have changed.
-  void ReportStats(int64 active_time_seconds, base::Time now);
-
   // Reads the current OS version from /etc/lsb-release and hashes it
   // to a unsigned 32-bit int.
   uint32 GetOsVersionHash();
 
+  // Updates stats, additionally sending them to UMA if enough time has elapsed
+  // since the last report.
+  void UpdateStats(base::TimeTicks now_ticks, base::Time now_wall_time);
+
+  // Invoked periodically by |update_stats_timeout_id_| to call UpdateStats().
+  static gboolean HandleUpdateStatsTimeout(gpointer data);
+
   // Test mode.
   bool testing_;
 
@@ -345,20 +277,11 @@
   // TimeTicks ensures a monotonically increasing TimeDelta.
   base::TimeTicks network_state_last_;
 
-  // Current power state.
-  PowerState power_state_;
+  // The last time that UpdateStats() was called.
+  base::TimeTicks last_update_stats_time_;
 
-  // Current user session state.
-  SessionState session_state_;
-
-  // Is the user currently active: power is on, user session has
-  // started, screen is not locked.
-  bool user_active_;
-
-  // 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_;
+  // ID of a GLib timeout that repeatedly runs UpdateStats().
+  gint update_stats_timeout_id_;
 
   // Sleep period until the next daily usage aggregation performed by
   // the daily use monitor (see ScheduleUseMonitor).
diff --git a/metrics_daemon_test.cc b/metrics_daemon_test.cc
index e83ad4d..de4aab6 100644
--- a/metrics_daemon_test.cc
+++ b/metrics_daemon_test.cc
@@ -20,13 +20,14 @@
 using base::FilePath;
 using base::StringPrintf;
 using base::Time;
+using base::TimeDelta;
 using base::TimeTicks;
 using std::string;
 using std::vector;
 using ::testing::_;
+using ::testing::AtLeast;
 using ::testing::Return;
 using ::testing::StrictMock;
-using ::testing::AtLeast;
 using chromeos_metrics::PersistentIntegerMock;
 
 static const int kSecondsPerDay = 24 * 60 * 60;
@@ -45,15 +46,6 @@
 static const char kFakeScalingMaxFreqPath[] = "fake-scaling-max-freq";
 static const char kFakeCpuinfoMaxFreqPath[] = "fake-cpuinfo-max-freq";
 
-// 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) {}
-};
-
 class MetricsDaemonTest : public testing::Test {
  protected:
   virtual void SetUp() {
@@ -71,11 +63,6 @@
     daemon_.Init(true, &metrics_lib_, kFakeDiskStatsPath, kFakeVmStatsPath,
         kFakeScalingMaxFreqPath, kFakeCpuinfoMaxFreqPath);
 
-    EXPECT_FALSE(daemon_.user_active_);
-    EXPECT_TRUE(daemon_.user_active_last_.is_null());
-    EXPECT_EQ(MetricsDaemon::kUnknownPowerState, daemon_.power_state_);
-    EXPECT_EQ(MetricsDaemon::kUnknownSessionState, daemon_.session_state_);
-
     base::DeleteFile(FilePath(kTestDir), true);
     base::CreateDirectory(FilePath(kTestDir));
 
@@ -133,24 +120,13 @@
 
   // Adds a metrics library mock expectation that the specified metric
   // will be generated.
-  void ExpectSample(int sample) {
-    EXPECT_CALL(metrics_lib_, SendToUMA(_, sample, _, _, _))
+  void ExpectSample(const std::string& name, int sample) {
+    EXPECT_CALL(metrics_lib_, SendToUMA(name, sample, _, _, _))
         .Times(1)
         .WillOnce(Return(true))
         .RetiresOnSaturation();
   }
 
-  // Adds a metrics library mock expectation that the specified daily
-  // use time metric will be generated.
-  void ExpectDailyUseTimeSample(int sample) {
-    ExpectSample(sample);
-  }
-
-  // Converts from seconds to a Time object.
-  Time TestTime(int64 seconds) {
-    return Time::FromInternalValue(seconds * Time::kMicrosecondsPerSecond);
-  }
-
   // Creates a new DBus signal message with zero or more string arguments.
   // The message can be deallocated through DeleteDBusMessage.
   //
@@ -229,33 +205,15 @@
 }
 
 TEST_F(MetricsDaemonTest, ReportDailyUse) {
-  ExpectDailyUseTimeSample(/* sample */ 2);
-  daemon_.ReportDailyUse(/* count */ 90);
+  ExpectSample("Logging.DailyUseTime", 2);
+  daemon_.ReportDailyUse(90);
 
-  ExpectDailyUseTimeSample(/* sample */ 1);
-  daemon_.ReportDailyUse(/* count */ 89);
+  ExpectSample("Logging.DailyUseTime", 1);
+  daemon_.ReportDailyUse(89);
 
   // There should be no metrics generated for the calls below.
-  daemon_.ReportDailyUse(/* count */ 0);
-  daemon_.ReportDailyUse(/* count */ -5);
-}
-
-TEST_F(MetricsDaemonTest, LookupPowerState) {
-  EXPECT_EQ(MetricsDaemon::kPowerStateOn,
-            daemon_.LookupPowerState("on"));
-  EXPECT_EQ(MetricsDaemon::kPowerStateMem,
-            daemon_.LookupPowerState("mem"));
-  EXPECT_EQ(MetricsDaemon::kUnknownPowerState,
-            daemon_.LookupPowerState("somestate"));
-}
-
-TEST_F(MetricsDaemonTest, LookupSessionState) {
-  EXPECT_EQ(MetricsDaemon::kSessionStateStarted,
-            daemon_.LookupSessionState("started"));
-  EXPECT_EQ(MetricsDaemon::kSessionStateStopped,
-            daemon_.LookupSessionState("stopped"));
-  EXPECT_EQ(MetricsDaemon::kUnknownSessionState,
-            daemon_.LookupSessionState("somestate"));
+  daemon_.ReportDailyUse(0);
+  daemon_.ReportDailyUse(-5);
 }
 
 TEST_F(MetricsDaemonTest, MessageFilter) {
@@ -279,44 +237,6 @@
   DeleteDBusMessage(msg);
 
   signal_args.clear();
-  signal_args.push_back("on");
-  msg = NewDBusSignalString(power_manager::kPowerManagerServicePath,
-                            power_manager::kPowerManagerInterface,
-                            power_manager::kPowerStateChangedSignal,
-                            signal_args);
-  EXPECT_EQ(MetricsDaemon::kUnknownPowerState, daemon_.power_state_);
-  res = MetricsDaemon::MessageFilter(/* connection */ NULL, msg, &daemon_);
-  EXPECT_EQ(MetricsDaemon::kPowerStateOn, daemon_.power_state_);
-  EXPECT_EQ(DBUS_HANDLER_RESULT_HANDLED, res);
-  DeleteDBusMessage(msg);
-
-  signal_args.clear();
-  IgnoreActiveUseUpdate();
-  msg = NewDBusSignalString(login_manager::kSessionManagerServicePath,
-                            login_manager::kSessionManagerInterface,
-                            login_manager::kScreenIsUnlockedSignal,
-                            signal_args);
-  EXPECT_FALSE(daemon_.user_active_);
-  res = MetricsDaemon::MessageFilter(/* connection */ NULL, msg, &daemon_);
-  EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(DBUS_HANDLER_RESULT_HANDLED, res);
-  DeleteDBusMessage(msg);
-
-  IgnoreActiveUseUpdate();
-  signal_args.clear();
-  signal_args.push_back("started");
-  signal_args.push_back("bob");  // arbitrary username
-  msg = NewDBusSignalString(login_manager::kSessionManagerServicePath,
-                            login_manager::kSessionManagerInterface,
-                            login_manager::kSessionStateChangedSignal,
-                            signal_args);
-  EXPECT_EQ(MetricsDaemon::kUnknownSessionState, daemon_.session_state_);
-  res = MetricsDaemon::MessageFilter(/* connection */ NULL, msg, &daemon_);
-  EXPECT_EQ(MetricsDaemon::kSessionStateStarted, daemon_.session_state_);
-  EXPECT_EQ(DBUS_HANDLER_RESULT_HANDLED, res);
-  DeleteDBusMessage(msg);
-
-  signal_args.clear();
   signal_args.push_back("randomstate");
   signal_args.push_back("bob");  // arbitrary username
   msg = NewDBusSignalString("/",
@@ -328,122 +248,12 @@
   DeleteDBusMessage(msg);
 }
 
-TEST_F(MetricsDaemonTest, PowerStateChanged) {
-  // Ignore calls to SendToUMA.
-  EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _)).Times(AtLeast(0));
-
-  ExpectActiveUseUpdate(0);
-  daemon_.SetUserActiveState(/* active */ true,
-                             TestTime(7 * kSecondsPerDay + 15));
-  EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(7 * kSecondsPerDay + 15), daemon_.user_active_last_);
-
-  ExpectActiveUseUpdate(30);
-  daemon_.PowerStateChanged("mem", TestTime(7 * kSecondsPerDay + 45));
-  EXPECT_EQ(MetricsDaemon::kPowerStateMem, daemon_.power_state_);
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(7 * kSecondsPerDay + 45), daemon_.user_active_last_);
-
-  daemon_.PowerStateChanged("on", TestTime(7 * kSecondsPerDay + 85));
-  EXPECT_EQ(MetricsDaemon::kPowerStateOn, daemon_.power_state_);
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(7 * kSecondsPerDay + 45), daemon_.user_active_last_);
-
-  ExpectActiveUseUpdate(0);
-  daemon_.PowerStateChanged("otherstate", TestTime(7 * kSecondsPerDay + 185));
-  EXPECT_EQ(MetricsDaemon::kUnknownPowerState, daemon_.power_state_);
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(7 * kSecondsPerDay + 185), daemon_.user_active_last_);
-}
-
 TEST_F(MetricsDaemonTest, SendSample) {
-  ExpectSample(3);
+  ExpectSample("Dummy.Metric", 3);
   daemon_.SendSample("Dummy.Metric", /* sample */ 3,
                      /* min */ 1, /* max */ 100, /* buckets */ 50);
 }
 
-TEST_F(MetricsDaemonTest, SessionStateChanged) {
-  // Ignore calls to SendToUMA.
-  EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _)).Times(AtLeast(0));
-
-  ExpectActiveUseUpdate(0);
-  daemon_.SessionStateChanged("started", TestTime(15 * kSecondsPerDay + 20));
-  EXPECT_EQ(MetricsDaemon::kSessionStateStarted, daemon_.session_state_);
-  EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(15 * kSecondsPerDay + 20), daemon_.user_active_last_);
-
-  ExpectActiveUseUpdate(130);
-  daemon_.SessionStateChanged("stopped", TestTime(15 * kSecondsPerDay + 150));
-  EXPECT_EQ(MetricsDaemon::kSessionStateStopped, daemon_.session_state_);
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(15 * kSecondsPerDay + 150), daemon_.user_active_last_);
-
-  ExpectActiveUseUpdate(0);
-  daemon_.SessionStateChanged("otherstate",
-                              TestTime(15 * kSecondsPerDay + 300));
-  EXPECT_EQ(MetricsDaemon::kUnknownSessionState, daemon_.session_state_);
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(15 * kSecondsPerDay + 300), daemon_.user_active_last_);
-}
-
-TEST_F(MetricsDaemonTest, SetUserActiveState) {
-  // Ignore calls to SendToUMA.
-  EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _)).Times(AtLeast(0));
-
-  ExpectActiveUseUpdate(0);
-  daemon_.SetUserActiveState(/* active */ false,
-                             TestTime(5 * kSecondsPerDay + 10));
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(5 * kSecondsPerDay + 10), daemon_.user_active_last_);
-
-  ExpectActiveUseUpdate(0);
-  daemon_.SetUserActiveState(/* active */ true,
-                             TestTime(6 * kSecondsPerDay + 20));
-  EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(6 * kSecondsPerDay + 20), daemon_.user_active_last_);
-
-  ExpectActiveUseUpdate(100);
-  daemon_.SetUserActiveState(/* active */ true,
-                             TestTime(6 * kSecondsPerDay + 120));
-  EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(6 * kSecondsPerDay + 120), daemon_.user_active_last_);
-
-  ExpectActiveUseUpdate(110);
-  daemon_.SetUserActiveState(/* active */ false,
-                             TestTime(6 * kSecondsPerDay + 230));
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(6 * kSecondsPerDay + 230), daemon_.user_active_last_);
-
-  ExpectActiveUseUpdate(0);
-  daemon_.SetUserActiveState(/* active */ false,
-                             TestTime(6 * kSecondsPerDay + 260));
-  EXPECT_FALSE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(6 * kSecondsPerDay + 260), daemon_.user_active_last_);
-}
-
-TEST_F(MetricsDaemonTest, SetUserActiveStateTimeJump) {
-  // Ignore calls to SendToUMA.
-  EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _)).Times(AtLeast(0));
-
-  ExpectActiveUseUpdate(0);
-  daemon_.SetUserActiveState(/* active */ true,
-                             TestTime(10 * kSecondsPerDay + 500));
-  EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(10 * kSecondsPerDay + 500), daemon_.user_active_last_);
-
-  ExpectActiveUseUpdate(0);
-  daemon_.SetUserActiveState(/* active */ true,
-                             TestTime(10 * kSecondsPerDay + 300));
-  EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(10 * kSecondsPerDay + 300), daemon_.user_active_last_);
-
-  ExpectActiveUseUpdate(0);
-  daemon_.SetUserActiveState(/* active */ true,
-                             TestTime(10 * kSecondsPerDay + 1000));
-  EXPECT_TRUE(daemon_.user_active_);
-  EXPECT_EQ(TestTime(10 * kSecondsPerDay + 1000), daemon_.user_active_last_);
-}
-
 TEST_F(MetricsDaemonTest, ReportDiskStats) {
   long int read_sectors_now, write_sectors_now;
 
diff --git a/power_states.h b/power_states.h
deleted file mode 100644
index 74fbfec..0000000
--- a/power_states.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// A table of power states, to be included when building tabular things.
-//
-// See network_states.h for details.
-
-
-#ifndef STATE
-#define STATE(name, capname)
-#endif
-
-STATE(on, On)
-STATE(mem, Mem)
-
-#undef STATE
diff --git a/session_states.h b/session_states.h
deleted file mode 100644
index 293dbd9..0000000
--- a/session_states.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// A table of user session states, to be included when building tabular things.
-//
-// See network_states.h for details.
-
-
-#ifndef STATE
-#define STATE(name, capname)
-#endif
-
-STATE(started, Started)
-STATE(stopped, Stopped)
-
-#undef STATE