152e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET/* 252e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * Copyright (C) 2015 The Android Open Source Project 352e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * 452e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * Licensed under the Apache License, Version 2.0 (the "License"); 552e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * you may not use this file except in compliance with the License. 652e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * You may obtain a copy of the License at 752e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * 852e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * http://www.apache.org/licenses/LICENSE-2.0 952e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * 1052e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * Unless required by applicable law or agreed to in writing, software 1152e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * distributed under the License is distributed on an "AS IS" BASIS, 1252e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1352e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * See the License for the specific language governing permissions and 1452e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET * limitations under the License. 1552e5b99983c1f7ff0b9a1f3b4b80d779073b21c8Bertrand SIMONNET */ 16be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 17be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha// Timer - class that provides timer tracking. 18be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 19be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha#ifndef METRICS_TIMER_H_ 20be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha#define METRICS_TIMER_H_ 21be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 226c9fbb9a3aaee50302d54de8f27fc712c836b9eaBertrand SIMONNET#include <memory> 23be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha#include <string> 24be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 25652d6971b19c2db2d3dcd1f8db36abadfc22079eBen Chan#include <base/macros.h> 262e6543ddad0b7d64697bb2326a5cfd1ab835a489Ben Chan#include <base/time/time.h> 27be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha#include <gtest/gtest_prod.h> // for FRIEND_TEST 28be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 29be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rochaclass MetricsLibraryInterface; 30be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 31be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rochanamespace chromeos_metrics { 32be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 33be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rochaclass TimerInterface { 34be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha public: 35be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual ~TimerInterface() {} 36be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 37be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual bool Start() = 0; 38be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual bool Stop() = 0; 39be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual bool Reset() = 0; 40be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual bool HasStarted() const = 0; 41be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha}; 42be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 43be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha// Wrapper for calls to the system clock. 44be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rochaclass ClockWrapper { 45be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha public: 46be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha ClockWrapper() {} 47be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual ~ClockWrapper() {} 48be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 49be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Returns the current time from the system. 50be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual base::TimeTicks GetCurrentTime() const; 51be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 52be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha private: 53be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha DISALLOW_COPY_AND_ASSIGN(ClockWrapper); 54be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha}; 55be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 56be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha// Implements a Timer. 57be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rochaclass Timer : public TimerInterface { 58be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha public: 59be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha Timer(); 60be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual ~Timer() {} 61be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 62be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Starts the timer. If a timer is already running, also resets current 63be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // timer. Always returns true. 64be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual bool Start(); 65be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 66be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Stops the timer and calculates the total time elapsed between now and when 67be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Start() was called. Note that this method needs a prior call to Start(). 68be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Otherwise, it fails (returns false). 69be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual bool Stop(); 70be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 710672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync // Pauses a timer. If the timer is stopped, this call starts the timer in 720672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync // the paused state. Fails (returns false) if the timer is already paused. 730672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync virtual bool Pause(); 740672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync 750672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync // Restarts a paused timer (or starts a stopped timer). This method fails 760672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync // (returns false) if the timer is already running; otherwise, returns true. 770672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync virtual bool Resume(); 780672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync 79be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Resets the timer, erasing the current duration being tracked. Always 80be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // returns true. 81be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual bool Reset(); 82be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 83be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Returns whether the timer has started or not. 84be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual bool HasStarted() const; 85be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 86be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Stores the current elapsed time in |elapsed_time|. If timer is stopped, 87be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // stores the elapsed time from when Stop() was last called. Otherwise, 88be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // calculates and stores the elapsed time since the last Start(). 89be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Returns false if the timer was never Start()'ed or if called with a null 90be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // pointer argument. 91be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual bool GetElapsedTime(base::TimeDelta* elapsed_time) const; 92be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 93be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha private: 940672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync enum TimerState { kTimerStopped, kTimerRunning, kTimerPaused }; 95be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha friend class TimerTest; 96be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha friend class TimerReporterTest; 970672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerReporterTest, StartStopReport); 980672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, InvalidElapsedTime); 990672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, InvalidStop); 1000672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, PauseResumeStop); 1010672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, PauseStartStopResume); 1020672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, PauseStop); 103be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha FRIEND_TEST(TimerTest, Reset); 1040672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, ReStart); 1050672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, ResumeStartStopPause); 106be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha FRIEND_TEST(TimerTest, SeparatedTimers); 1070672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, StartPauseResumePauseResumeStop); 1080672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, StartPauseResumePauseStop); 1090672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, StartPauseResumeStop); 1100672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, StartPauseStop); 1110672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, StartResumeStop); 1120672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync FRIEND_TEST(TimerTest, StartStop); 113be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 114be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Elapsed time of the last use of the timer. 115be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha base::TimeDelta elapsed_time_; 116be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 117be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Starting time value. 118be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha base::TimeTicks start_time_; 119be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 1200672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync // Whether the timer is running, stopped, or paused. 1210672655fa66deb6dd772a584b82e2c5bbf4cf847repo sync TimerState timer_state_; 122be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 123be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Wrapper for the calls to the system clock. 1246c9fbb9a3aaee50302d54de8f27fc712c836b9eaBertrand SIMONNET std::unique_ptr<ClockWrapper> clock_wrapper_; 125be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 126be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha DISALLOW_COPY_AND_ASSIGN(Timer); 127be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha}; 128be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 129be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha// Extends the Timer class to report the elapsed time in milliseconds through 130be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha// the UMA metrics library. 131be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rochaclass TimerReporter : public Timer { 132be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha public: 133be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Initializes the timer by providing a |histogram_name| to report to with 134be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // |min|, |max| and |num_buckets| attributes for the histogram. 135be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha TimerReporter(const std::string& histogram_name, int min, int max, 136be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha int num_buckets); 137be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual ~TimerReporter() {} 138be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 139be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Sets the metrics library used by all instances of this class. 140be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha static void set_metrics_lib(MetricsLibraryInterface* metrics_lib) { 141be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha metrics_lib_ = metrics_lib; 142be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha } 143be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 144be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Reports the current duration to UMA, in milliseconds. Returns false if 1451bc9ce0294a0107b6d087e73164eb786cc658704repo sync // there is nothing to report, e.g. a metrics library is not set. 146be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha virtual bool ReportMilliseconds() const; 147be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 148be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha // Accessor methods. 149be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha const std::string& histogram_name() const { return histogram_name_; } 150be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha int min() const { return min_; } 151be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha int max() const { return max_; } 152be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha int num_buckets() const { return num_buckets_; } 153be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 154be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha private: 155be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha friend class TimerReporterTest; 156be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha FRIEND_TEST(TimerReporterTest, StartStopReport); 157be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha FRIEND_TEST(TimerReporterTest, InvalidReport); 158be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 159be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha static MetricsLibraryInterface* metrics_lib_; 160be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha std::string histogram_name_; 161be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha int min_; 162be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha int max_; 163be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha int num_buckets_; 164be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 165be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha DISALLOW_COPY_AND_ASSIGN(TimerReporter); 166be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha}; 167be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 168be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha} // namespace chromeos_metrics 169be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha 170be388f301b9fef2e4ecd0cd9612dfe9216b5b266Bruno Rocha#endif // METRICS_TIMER_H_ 171