1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // Timer - class that provides timer tracking.
18 
19 #ifndef METRICS_TIMER_H_
20 #define METRICS_TIMER_H_
21 
22 #include <memory>
23 #include <string>
24 
25 #include <base/macros.h>
26 #include <base/time/time.h>
27 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
28 
29 class MetricsLibraryInterface;
30 
31 namespace chromeos_metrics {
32 
33 class TimerInterface {
34  public:
~TimerInterface()35   virtual ~TimerInterface() {}
36 
37   virtual bool Start() = 0;
38   virtual bool Stop() = 0;
39   virtual bool Reset() = 0;
40   virtual bool HasStarted() const = 0;
41 };
42 
43 // Wrapper for calls to the system clock.
44 class ClockWrapper {
45  public:
ClockWrapper()46   ClockWrapper() {}
~ClockWrapper()47   virtual ~ClockWrapper() {}
48 
49   // Returns the current time from the system.
50   virtual base::TimeTicks GetCurrentTime() const;
51 
52  private:
53   DISALLOW_COPY_AND_ASSIGN(ClockWrapper);
54 };
55 
56 // Implements a Timer.
57 class Timer : public TimerInterface {
58  public:
59   Timer();
~Timer()60   virtual ~Timer() {}
61 
62   // Starts the timer. If a timer is already running, also resets current
63   // timer. Always returns true.
64   virtual bool Start();
65 
66   // Stops the timer and calculates the total time elapsed between now and when
67   // Start() was called. Note that this method needs a prior call to Start().
68   // Otherwise, it fails (returns false).
69   virtual bool Stop();
70 
71   // Pauses a timer.  If the timer is stopped, this call starts the timer in
72   // the paused state. Fails (returns false) if the timer is already paused.
73   virtual bool Pause();
74 
75   // Restarts a paused timer (or starts a stopped timer). This method fails
76   // (returns false) if the timer is already running; otherwise, returns true.
77   virtual bool Resume();
78 
79   // Resets the timer, erasing the current duration being tracked. Always
80   // returns true.
81   virtual bool Reset();
82 
83   // Returns whether the timer has started or not.
84   virtual bool HasStarted() const;
85 
86   // Stores the current elapsed time in |elapsed_time|. If timer is stopped,
87   // stores the elapsed time from when Stop() was last called. Otherwise,
88   // calculates and stores the elapsed time since the last Start().
89   // Returns false if the timer was never Start()'ed or if called with a null
90   // pointer argument.
91   virtual bool GetElapsedTime(base::TimeDelta* elapsed_time) const;
92 
93  private:
94   enum TimerState { kTimerStopped, kTimerRunning, kTimerPaused };
95   friend class TimerTest;
96   friend class TimerReporterTest;
97   FRIEND_TEST(TimerReporterTest, StartStopReport);
98   FRIEND_TEST(TimerTest, InvalidElapsedTime);
99   FRIEND_TEST(TimerTest, InvalidStop);
100   FRIEND_TEST(TimerTest, PauseResumeStop);
101   FRIEND_TEST(TimerTest, PauseStartStopResume);
102   FRIEND_TEST(TimerTest, PauseStop);
103   FRIEND_TEST(TimerTest, Reset);
104   FRIEND_TEST(TimerTest, ReStart);
105   FRIEND_TEST(TimerTest, ResumeStartStopPause);
106   FRIEND_TEST(TimerTest, SeparatedTimers);
107   FRIEND_TEST(TimerTest, StartPauseResumePauseResumeStop);
108   FRIEND_TEST(TimerTest, StartPauseResumePauseStop);
109   FRIEND_TEST(TimerTest, StartPauseResumeStop);
110   FRIEND_TEST(TimerTest, StartPauseStop);
111   FRIEND_TEST(TimerTest, StartResumeStop);
112   FRIEND_TEST(TimerTest, StartStop);
113 
114   // Elapsed time of the last use of the timer.
115   base::TimeDelta elapsed_time_;
116 
117   // Starting time value.
118   base::TimeTicks start_time_;
119 
120   // Whether the timer is running, stopped, or paused.
121   TimerState timer_state_;
122 
123   // Wrapper for the calls to the system clock.
124   std::unique_ptr<ClockWrapper> clock_wrapper_;
125 
126   DISALLOW_COPY_AND_ASSIGN(Timer);
127 };
128 
129 // Extends the Timer class to report the elapsed time in milliseconds through
130 // the UMA metrics library.
131 class TimerReporter : public Timer {
132  public:
133   // Initializes the timer by providing a |histogram_name| to report to with
134   // |min|, |max| and |num_buckets| attributes for the histogram.
135   TimerReporter(const std::string& histogram_name, int min, int max,
136                 int num_buckets);
~TimerReporter()137   virtual ~TimerReporter() {}
138 
139   // Sets the metrics library used by all instances of this class.
set_metrics_lib(MetricsLibraryInterface * metrics_lib)140   static void set_metrics_lib(MetricsLibraryInterface* metrics_lib) {
141     metrics_lib_ = metrics_lib;
142   }
143 
144   // Reports the current duration to UMA, in milliseconds. Returns false if
145   // there is nothing to report, e.g. a metrics library is not set.
146   virtual bool ReportMilliseconds() const;
147 
148   // Accessor methods.
histogram_name()149   const std::string& histogram_name() const { return histogram_name_; }
min()150   int min() const { return min_; }
max()151   int max() const { return max_; }
num_buckets()152   int num_buckets() const { return num_buckets_; }
153 
154  private:
155   friend class TimerReporterTest;
156   FRIEND_TEST(TimerReporterTest, StartStopReport);
157   FRIEND_TEST(TimerReporterTest, InvalidReport);
158 
159   static MetricsLibraryInterface* metrics_lib_;
160   std::string histogram_name_;
161   int min_;
162   int max_;
163   int num_buckets_;
164 
165   DISALLOW_COPY_AND_ASSIGN(TimerReporter);
166 };
167 
168 }  // namespace chromeos_metrics
169 
170 #endif  // METRICS_TIMER_H_
171