1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef COMPONENTS_GUEST_OS_GUEST_OS_ENGAGEMENT_METRICS_H_
6 #define COMPONENTS_GUEST_OS_GUEST_OS_ENGAGEMENT_METRICS_H_
7 
8 #include <memory>
9 
10 #include "base/macros.h"
11 #include "base/time/time.h"
12 #include "base/timer/timer.h"
13 #include "chromeos/dbus/power/power_manager_client.h"
14 #include "components/session_manager/core/session_manager_observer.h"
15 #include "ui/wm/public/activation_change_observer.h"
16 
17 class PrefService;
18 
19 namespace aura {
20 class Window;
21 }  // namespace aura
22 
23 namespace base {
24 class Clock;
25 class TickClock;
26 }  // namespace base
27 
28 namespace guest_os {
29 
30 // A class for recording engagement metrics. Calculates and reports daily
31 // totals for the following metrics:
32 // - Foo.EngagementTime.Total: Engaged session time, i.e. excluding when the
33 // screen is locked or dim due to user idle. To allow comparisons with the
34 // other metrics, this class should only be instantiated when the relevant
35 // Guest OS is supported.
36 // - Foo.EngagementTime.Foreground: Time when the user is engaged and focused
37 // on a matching window.
38 // - Foo.EngagementTime.Background: Time when the user is engaged and not
39 // focused on a matching window, but the Guest OS is otherwise active in the
40 // background.
41 // - Foo.Engagement.FooTotal: Total of Foreground and Background.
42 class GuestOsEngagementMetrics : public wm::ActivationChangeObserver,
43                                  public session_manager::SessionManagerObserver,
44                                  public chromeos::PowerManagerClient::Observer {
45  public:
46   using WindowMatcher = base::RepeatingCallback<bool(const aura::Window*)>;
47 
48   GuestOsEngagementMetrics(PrefService* pref_service,
49                            WindowMatcher window_matcher,
50                            const std::string& pref_prefix,
51                            const std::string& uma_name);
52   ~GuestOsEngagementMetrics() override;
53 
54   // Instead of using |window_matcher_|, we let consumers define when the Guest
55   // OS is active in the background. This function should be called whenever
56   // changes.
57   void SetBackgroundActive(bool background_active);
58 
59   void SetClocksForTesting(base::Clock* clock, base::TickClock* tick_clock);
60 
61   // wm::ActivationChangeObserver:
62   void OnWindowActivated(wm::ActivationChangeObserver::ActivationReason reason,
63                          aura::Window* gained_active,
64                          aura::Window* lost_active) override;
65 
66   // session_manager::SessionManagerObserver:
67   void OnSessionStateChanged() override;
68 
69   // chromeos::PowerManagerClient::Observer:
70   void ScreenIdleStateChanged(
71       const power_manager::ScreenIdleState& proto) override;
72 
73  private:
74   // Restores accumulated engagement time in previous sessions from profile
75   // preferences.
76   void RestoreEngagementTimeFromPrefs();
77 
78   // Called periodically to save accumulated results to profile preferences.
79   void SaveEngagementTimeToPrefs();
80 
81   // Called whenever engagement state is changed. Time spent in last state is
82   // accumulated to corresponding metrics.
83   void UpdateEngagementTime();
84 
85   // Records accumulated engagement time metrics to UMA if necessary (i.e. day
86   // has changed).
87   void RecordEngagementTimeToUmaIfNeeded();
88 
89   // Resets accumulated engagement times to zero, and updates both OS version
90   // and day ID.
91   void ResetEngagementTimePrefs();
92 
93   bool ShouldAccumulateEngagementTotalTime() const;
94   bool ShouldAccumulateEngagementForegroundTime() const;
95   bool ShouldAccumulateEngagementBackgroundTime() const;
96 
97   bool ShouldRecordEngagementTimeToUma() const;
98 
99   PrefService* const pref_service_;
100 
101   WindowMatcher window_matcher_;
102   std::string pref_prefix_;
103   std::string uma_name_;
104 
105   // |clock_| is used for determining when to log to UMA, while |tick_clock_|
106   // is used to calculate elapsed time.
107   const base::Clock* clock_;
108   const base::TickClock* tick_clock_;
109   base::RepeatingTimer update_engagement_time_timer_;
110   base::RepeatingTimer save_engagement_time_to_prefs_timer_;
111   base::TimeTicks last_update_ticks_;
112 
113   // States for determining which engagement metrics should we accumulate to.
114   bool session_active_ = false;
115   bool screen_dimmed_ = false;
116   bool background_active_ = false;
117   bool matched_window_active_ = false;
118 
119   // Accumulated results and associated state which are saved to profile
120   // preferences at fixed interval.
121   int day_id_ = 0;
122   base::TimeDelta engagement_time_total_;
123   base::TimeDelta engagement_time_foreground_;
124   base::TimeDelta engagement_time_background_;
125 
126   DISALLOW_COPY_AND_ASSIGN(GuestOsEngagementMetrics);
127 };
128 
129 }  // namespace guest_os
130 
131 #endif  // COMPONENTS_GUEST_OS_GUEST_OS_ENGAGEMENT_METRICS_H_
132