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
29class MetricsLibraryInterface;
30
31namespace chromeos_metrics {
32
33class TimerInterface {
34 public:
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.
44class ClockWrapper {
45 public:
46  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.
57class Timer : public TimerInterface {
58 public:
59  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.
131class 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);
137  virtual ~TimerReporter() {}
138
139  // Sets the metrics library used by all instances of this class.
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.
149  const std::string& histogram_name() const { return histogram_name_; }
150  int min() const { return min_; }
151  int max() const { return max_; }
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