|  | /* | 
|  | * Copyright (C) 2015 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  |  | 
|  | // Timer - class that provides timer tracking. | 
|  |  | 
|  | #ifndef METRICS_TIMER_H_ | 
|  | #define METRICS_TIMER_H_ | 
|  |  | 
|  | #include <string> | 
|  |  | 
|  | #include <base/macros.h> | 
|  | #include <base/memory/scoped_ptr.h> | 
|  | #include <base/time/time.h> | 
|  | #include <gtest/gtest_prod.h>  // for FRIEND_TEST | 
|  |  | 
|  | class MetricsLibraryInterface; | 
|  |  | 
|  | namespace chromeos_metrics { | 
|  |  | 
|  | class TimerInterface { | 
|  | public: | 
|  | virtual ~TimerInterface() {} | 
|  |  | 
|  | virtual bool Start() = 0; | 
|  | virtual bool Stop() = 0; | 
|  | virtual bool Reset() = 0; | 
|  | virtual bool HasStarted() const = 0; | 
|  | }; | 
|  |  | 
|  | // Wrapper for calls to the system clock. | 
|  | class ClockWrapper { | 
|  | public: | 
|  | ClockWrapper() {} | 
|  | virtual ~ClockWrapper() {} | 
|  |  | 
|  | // Returns the current time from the system. | 
|  | virtual base::TimeTicks GetCurrentTime() const; | 
|  |  | 
|  | private: | 
|  | DISALLOW_COPY_AND_ASSIGN(ClockWrapper); | 
|  | }; | 
|  |  | 
|  | // Implements a Timer. | 
|  | class Timer : public TimerInterface { | 
|  | public: | 
|  | Timer(); | 
|  | virtual ~Timer() {} | 
|  |  | 
|  | // Starts the timer. If a timer is already running, also resets current | 
|  | // timer. Always returns true. | 
|  | virtual bool Start(); | 
|  |  | 
|  | // Stops the timer and calculates the total time elapsed between now and when | 
|  | // Start() was called. Note that this method needs a prior call to Start(). | 
|  | // Otherwise, it fails (returns false). | 
|  | virtual bool Stop(); | 
|  |  | 
|  | // Pauses a timer.  If the timer is stopped, this call starts the timer in | 
|  | // the paused state. Fails (returns false) if the timer is already paused. | 
|  | virtual bool Pause(); | 
|  |  | 
|  | // Restarts a paused timer (or starts a stopped timer). This method fails | 
|  | // (returns false) if the timer is already running; otherwise, returns true. | 
|  | virtual bool Resume(); | 
|  |  | 
|  | // Resets the timer, erasing the current duration being tracked. Always | 
|  | // returns true. | 
|  | virtual bool Reset(); | 
|  |  | 
|  | // Returns whether the timer has started or not. | 
|  | virtual bool HasStarted() const; | 
|  |  | 
|  | // Stores the current elapsed time in |elapsed_time|. If timer is stopped, | 
|  | // stores the elapsed time from when Stop() was last called. Otherwise, | 
|  | // calculates and stores the elapsed time since the last Start(). | 
|  | // Returns false if the timer was never Start()'ed or if called with a null | 
|  | // pointer argument. | 
|  | virtual bool GetElapsedTime(base::TimeDelta* elapsed_time) const; | 
|  |  | 
|  | private: | 
|  | enum TimerState { kTimerStopped, kTimerRunning, kTimerPaused }; | 
|  | friend class TimerTest; | 
|  | friend class TimerReporterTest; | 
|  | FRIEND_TEST(TimerReporterTest, StartStopReport); | 
|  | FRIEND_TEST(TimerTest, InvalidElapsedTime); | 
|  | FRIEND_TEST(TimerTest, InvalidStop); | 
|  | FRIEND_TEST(TimerTest, PauseResumeStop); | 
|  | FRIEND_TEST(TimerTest, PauseStartStopResume); | 
|  | FRIEND_TEST(TimerTest, PauseStop); | 
|  | FRIEND_TEST(TimerTest, Reset); | 
|  | FRIEND_TEST(TimerTest, ReStart); | 
|  | FRIEND_TEST(TimerTest, ResumeStartStopPause); | 
|  | FRIEND_TEST(TimerTest, SeparatedTimers); | 
|  | FRIEND_TEST(TimerTest, StartPauseResumePauseResumeStop); | 
|  | FRIEND_TEST(TimerTest, StartPauseResumePauseStop); | 
|  | FRIEND_TEST(TimerTest, StartPauseResumeStop); | 
|  | FRIEND_TEST(TimerTest, StartPauseStop); | 
|  | FRIEND_TEST(TimerTest, StartResumeStop); | 
|  | FRIEND_TEST(TimerTest, StartStop); | 
|  |  | 
|  | // Elapsed time of the last use of the timer. | 
|  | base::TimeDelta elapsed_time_; | 
|  |  | 
|  | // Starting time value. | 
|  | base::TimeTicks start_time_; | 
|  |  | 
|  | // Whether the timer is running, stopped, or paused. | 
|  | TimerState timer_state_; | 
|  |  | 
|  | // Wrapper for the calls to the system clock. | 
|  | scoped_ptr<ClockWrapper> clock_wrapper_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(Timer); | 
|  | }; | 
|  |  | 
|  | // Extends the Timer class to report the elapsed time in milliseconds through | 
|  | // the UMA metrics library. | 
|  | class TimerReporter : public Timer { | 
|  | public: | 
|  | // Initializes the timer by providing a |histogram_name| to report to with | 
|  | // |min|, |max| and |num_buckets| attributes for the histogram. | 
|  | TimerReporter(const std::string& histogram_name, int min, int max, | 
|  | int num_buckets); | 
|  | virtual ~TimerReporter() {} | 
|  |  | 
|  | // Sets the metrics library used by all instances of this class. | 
|  | static void set_metrics_lib(MetricsLibraryInterface* metrics_lib) { | 
|  | metrics_lib_ = metrics_lib; | 
|  | } | 
|  |  | 
|  | // Reports the current duration to UMA, in milliseconds. Returns false if | 
|  | // there is nothing to report, e.g. a metrics library is not set. | 
|  | virtual bool ReportMilliseconds() const; | 
|  |  | 
|  | // Accessor methods. | 
|  | const std::string& histogram_name() const { return histogram_name_; } | 
|  | int min() const { return min_; } | 
|  | int max() const { return max_; } | 
|  | int num_buckets() const { return num_buckets_; } | 
|  |  | 
|  | private: | 
|  | friend class TimerReporterTest; | 
|  | FRIEND_TEST(TimerReporterTest, StartStopReport); | 
|  | FRIEND_TEST(TimerReporterTest, InvalidReport); | 
|  |  | 
|  | static MetricsLibraryInterface* metrics_lib_; | 
|  | std::string histogram_name_; | 
|  | int min_; | 
|  | int max_; | 
|  | int num_buckets_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(TimerReporter); | 
|  | }; | 
|  |  | 
|  | }  // namespace chromeos_metrics | 
|  |  | 
|  | #endif  // METRICS_TIMER_H_ |