• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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()22 void ReportHighResolutionTimerUsage() {
23   UMA_HISTOGRAM_PERCENTAGE("Windows.HighResolutionTimerUsage",
24                            Time::GetHighResolutionTimerUsage());
25   // Reset usage for the next interval.
26   Time::ResetHighResolutionTimerUsage();
27 }
28 
HighResolutionTimerAllowed()29 bool HighResolutionTimerAllowed() {
30   return !CommandLine::ForCurrentProcess()->HasSwitch(
31       switches::kDisableHighResTimer);
32 }
33 
34 }  // namespace
35 
HighResolutionTimerManager()36 HighResolutionTimerManager::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()58 HighResolutionTimerManager::~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)67 void HighResolutionTimerManager::OnBatteryPowerStatusChange(
68     base::PowerStateObserver::BatteryPowerStatus battery_power_status) {
69   DCHECK(HighResolutionTimerAllowed());
70   UseHiResClock(battery_power_status !=
71                 PowerStateObserver::BatteryPowerStatus::kBatteryPower);
72 }
73 
OnSuspend()74 void HighResolutionTimerManager::OnSuspend() {
75   DCHECK(HighResolutionTimerAllowed());
76   // Stop polling the usage to avoid including the standby time.
77   timer_.Stop();
78 }
79 
OnResume()80 void HighResolutionTimerManager::OnResume() {
81   DCHECK(HighResolutionTimerAllowed());
82   // Resume polling the usage.
83   Time::ResetHighResolutionTimerUsage();
84   timer_.Reset();
85 }
86 
UseHiResClock(bool use)87 void 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