1 // Copyright 2011 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/timer/hi_res_timer_manager.h" 6 7 #include <algorithm> 8 9 #include "base/atomicops.h" 10 #include "base/base_switches.h" 11 #include "base/command_line.h" 12 #include "base/metrics/histogram_macros.h" 13 #include "base/power_monitor/power_monitor.h" 14 #include "base/time/time.h" 15 16 namespace base { 17 18 namespace { 19 20 constexpr TimeDelta kUsageSampleInterval = Minutes(10); 21 ReportHighResolutionTimerUsage()22void ReportHighResolutionTimerUsage() { 23 UMA_HISTOGRAM_PERCENTAGE("Windows.HighResolutionTimerUsage", 24 Time::GetHighResolutionTimerUsage()); 25 // Reset usage for the next interval. 26 Time::ResetHighResolutionTimerUsage(); 27 } 28 HighResolutionTimerAllowed()29bool HighResolutionTimerAllowed() { 30 return !CommandLine::ForCurrentProcess()->HasSwitch( 31 switches::kDisableHighResTimer); 32 } 33 34 } // namespace 35 HighResolutionTimerManager()36HighResolutionTimerManager::HighResolutionTimerManager() 37 : hi_res_clock_available_(false) { 38 // Register for PowerMonitor callbacks only if high-resolution 39 // timers are allowed. If high-resolution timers are disabled 40 // we won't receive power state change callbacks and 41 // hi_res_clock_available_ will remain at its initial value. 42 if (HighResolutionTimerAllowed()) { 43 auto* power_monitor = base::PowerMonitor::GetInstance(); 44 DCHECK(power_monitor->IsInitialized()); 45 power_monitor->AddPowerSuspendObserver(this); 46 const bool on_battery = 47 power_monitor->AddPowerStateObserverAndReturnBatteryPowerStatus(this) == 48 PowerStateObserver::BatteryPowerStatus::kBatteryPower; 49 UseHiResClock(!on_battery); 50 51 // Start polling the high resolution timer usage. 52 Time::ResetHighResolutionTimerUsage(); 53 timer_.Start(FROM_HERE, kUsageSampleInterval, 54 BindRepeating(&ReportHighResolutionTimerUsage)); 55 } 56 } 57 ~HighResolutionTimerManager()58HighResolutionTimerManager::~HighResolutionTimerManager() { 59 if (HighResolutionTimerAllowed()) { 60 auto* power_monitor = base::PowerMonitor::GetInstance(); 61 power_monitor->RemovePowerSuspendObserver(this); 62 power_monitor->RemovePowerStateObserver(this); 63 UseHiResClock(false); 64 } 65 } 66 OnBatteryPowerStatusChange(base::PowerStateObserver::BatteryPowerStatus battery_power_status)67void HighResolutionTimerManager::OnBatteryPowerStatusChange( 68 base::PowerStateObserver::BatteryPowerStatus battery_power_status) { 69 DCHECK(HighResolutionTimerAllowed()); 70 UseHiResClock(battery_power_status != 71 PowerStateObserver::BatteryPowerStatus::kBatteryPower); 72 } 73 OnSuspend()74void HighResolutionTimerManager::OnSuspend() { 75 DCHECK(HighResolutionTimerAllowed()); 76 // Stop polling the usage to avoid including the standby time. 77 timer_.Stop(); 78 } 79 OnResume()80void HighResolutionTimerManager::OnResume() { 81 DCHECK(HighResolutionTimerAllowed()); 82 // Resume polling the usage. 83 Time::ResetHighResolutionTimerUsage(); 84 timer_.Reset(); 85 } 86 UseHiResClock(bool use)87void HighResolutionTimerManager::UseHiResClock(bool use) { 88 DCHECK(HighResolutionTimerAllowed()); 89 if (use == hi_res_clock_available_) 90 return; 91 hi_res_clock_available_ = use; 92 Time::EnableHighResolutionTimer(use); 93 } 94 95 } // namespace base 96