Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 1 | // Copyright 2013 The Chromium Authors |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 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/power_monitor/power_monitor.h" |
| 6 | |
| 7 | #include <utility> |
| 8 | |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 9 | #include "base/logging.h" |
| 10 | #include "base/no_destructor.h" |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 11 | #include "base/power_monitor/power_monitor_source.h" |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 12 | #include "base/trace_event/base_tracing.h" |
| 13 | #include "build/build_config.h" |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 14 | |
| 15 | namespace base { |
| 16 | |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 17 | void PowerMonitor::Initialize(std::unique_ptr<PowerMonitorSource> source) { |
| 18 | DCHECK(!IsInitialized()); |
| 19 | PowerMonitor* power_monitor = GetInstance(); |
| 20 | power_monitor->source_ = std::move(source); |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 21 | |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 22 | // When a power source is associated with the power monitor, ensure the |
| 23 | // initial state is propagated to observers, if needed. |
| 24 | PowerMonitor::NotifyPowerStateChange( |
| 25 | PowerMonitor::Source()->IsOnBatteryPower()); |
| 26 | |
| 27 | PowerMonitor::PowerMonitor::NotifyThermalStateChange( |
| 28 | PowerMonitor::Source()->GetCurrentThermalState()); |
| 29 | |
| 30 | PowerMonitor::PowerMonitor::NotifySpeedLimitChange( |
| 31 | PowerMonitor::Source()->GetInitialSpeedLimit()); |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 32 | } |
| 33 | |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 34 | bool PowerMonitor::IsInitialized() { |
| 35 | return GetInstance()->source_.get() != nullptr; |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 36 | } |
| 37 | |
| 38 | // static |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 39 | void PowerMonitor::AddPowerSuspendObserver(PowerSuspendObserver* obs) { |
| 40 | GetInstance()->power_suspend_observers_->AddObserver(obs); |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 41 | } |
| 42 | |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 43 | // static |
| 44 | void PowerMonitor::RemovePowerSuspendObserver(PowerSuspendObserver* obs) { |
| 45 | GetInstance()->power_suspend_observers_->RemoveObserver(obs); |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 46 | } |
| 47 | |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 48 | // static |
| 49 | void PowerMonitor::AddPowerStateObserver(PowerStateObserver* obs) { |
| 50 | GetInstance()->power_state_observers_->AddObserver(obs); |
| 51 | } |
| 52 | |
| 53 | // static |
| 54 | void PowerMonitor::RemovePowerStateObserver(PowerStateObserver* obs) { |
| 55 | GetInstance()->power_state_observers_->RemoveObserver(obs); |
| 56 | } |
| 57 | |
| 58 | // static |
| 59 | void PowerMonitor::AddPowerThermalObserver(PowerThermalObserver* obs) { |
| 60 | GetInstance()->thermal_state_observers_->AddObserver(obs); |
| 61 | } |
| 62 | |
| 63 | // static |
| 64 | void PowerMonitor::RemovePowerThermalObserver(PowerThermalObserver* obs) { |
| 65 | GetInstance()->thermal_state_observers_->RemoveObserver(obs); |
| 66 | } |
| 67 | |
| 68 | // static |
| 69 | bool PowerMonitor::AddPowerSuspendObserverAndReturnSuspendedState( |
| 70 | PowerSuspendObserver* obs) { |
| 71 | PowerMonitor* power_monitor = GetInstance(); |
| 72 | AutoLock auto_lock(power_monitor->is_system_suspended_lock_); |
| 73 | power_monitor->power_suspend_observers_->AddObserver(obs); |
| 74 | return power_monitor->is_system_suspended_; |
| 75 | } |
| 76 | |
| 77 | // static |
| 78 | bool PowerMonitor::AddPowerStateObserverAndReturnOnBatteryState( |
| 79 | PowerStateObserver* obs) { |
| 80 | PowerMonitor* power_monitor = GetInstance(); |
| 81 | AutoLock auto_lock(power_monitor->on_battery_power_lock_); |
| 82 | power_monitor->power_state_observers_->AddObserver(obs); |
| 83 | return power_monitor->on_battery_power_; |
| 84 | } |
| 85 | |
| 86 | // static |
| 87 | PowerThermalObserver::DeviceThermalState |
| 88 | PowerMonitor::AddPowerStateObserverAndReturnPowerThermalState( |
| 89 | PowerThermalObserver* obs) { |
| 90 | PowerMonitor* power_monitor = GetInstance(); |
| 91 | AutoLock auto_lock(power_monitor->power_thermal_state_lock_); |
| 92 | power_monitor->thermal_state_observers_->AddObserver(obs); |
| 93 | return power_monitor->power_thermal_state_; |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 94 | } |
| 95 | |
| 96 | PowerMonitorSource* PowerMonitor::Source() { |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 97 | return GetInstance()->source_.get(); |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 98 | } |
| 99 | |
| 100 | bool PowerMonitor::IsOnBatteryPower() { |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 101 | DCHECK(IsInitialized()); |
| 102 | PowerMonitor* power_monitor = GetInstance(); |
| 103 | AutoLock auto_lock(power_monitor->on_battery_power_lock_); |
| 104 | return power_monitor->on_battery_power_; |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 105 | } |
| 106 | |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 107 | TimeTicks PowerMonitor::GetLastSystemResumeTime() { |
| 108 | PowerMonitor* power_monitor = GetInstance(); |
| 109 | AutoLock auto_lock(power_monitor->is_system_suspended_lock_); |
| 110 | return power_monitor->last_system_resume_time_; |
| 111 | } |
| 112 | |
| 113 | void PowerMonitor::ShutdownForTesting() { |
| 114 | GetInstance()->source_ = nullptr; |
| 115 | |
| 116 | PowerMonitor* power_monitor = GetInstance(); |
| 117 | { |
| 118 | AutoLock auto_lock(power_monitor->is_system_suspended_lock_); |
| 119 | power_monitor->is_system_suspended_ = false; |
| 120 | power_monitor->last_system_resume_time_ = TimeTicks(); |
| 121 | } |
| 122 | { |
| 123 | AutoLock auto_lock(power_monitor->on_battery_power_lock_); |
| 124 | power_monitor->on_battery_power_ = false; |
| 125 | } |
| 126 | { |
| 127 | AutoLock auto_lock(power_monitor->power_thermal_state_lock_); |
| 128 | power_monitor->power_thermal_state_ = |
| 129 | PowerThermalObserver::DeviceThermalState::kUnknown; |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | // static |
| 134 | PowerThermalObserver::DeviceThermalState |
| 135 | PowerMonitor::GetCurrentThermalState() { |
| 136 | DCHECK(IsInitialized()); |
| 137 | return GetInstance()->source_->GetCurrentThermalState(); |
| 138 | } |
| 139 | |
| 140 | // static |
| 141 | void PowerMonitor::SetCurrentThermalState( |
| 142 | PowerThermalObserver::DeviceThermalState state) { |
| 143 | DCHECK(IsInitialized()); |
| 144 | GetInstance()->source_->SetCurrentThermalState(state); |
| 145 | } |
| 146 | |
| 147 | #if BUILDFLAG(IS_ANDROID) |
| 148 | int PowerMonitor::GetRemainingBatteryCapacity() { |
| 149 | DCHECK(IsInitialized()); |
| 150 | return PowerMonitor::Source()->GetRemainingBatteryCapacity(); |
| 151 | } |
| 152 | #endif // BUILDFLAG(IS_ANDROID) |
| 153 | |
| 154 | void PowerMonitor::NotifyPowerStateChange(bool on_battery_power) { |
| 155 | DCHECK(IsInitialized()); |
| 156 | DVLOG(1) << "PowerStateChange: " << (on_battery_power ? "On" : "Off") |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 157 | << " battery"; |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 158 | |
| 159 | PowerMonitor* power_monitor = GetInstance(); |
| 160 | AutoLock auto_lock(power_monitor->on_battery_power_lock_); |
| 161 | if (power_monitor->on_battery_power_ != on_battery_power) { |
| 162 | power_monitor->on_battery_power_ = on_battery_power; |
| 163 | GetInstance()->power_state_observers_->Notify( |
| 164 | FROM_HERE, &PowerStateObserver::OnPowerStateChange, on_battery_power); |
| 165 | } |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 166 | } |
| 167 | |
| 168 | void PowerMonitor::NotifySuspend() { |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 169 | DCHECK(IsInitialized()); |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 170 | TRACE_EVENT_INSTANT0("base", "PowerMonitor::NotifySuspend", |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 171 | TRACE_EVENT_SCOPE_PROCESS); |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 172 | DVLOG(1) << "Power Suspending"; |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 173 | |
| 174 | PowerMonitor* power_monitor = GetInstance(); |
| 175 | AutoLock auto_lock(power_monitor->is_system_suspended_lock_); |
| 176 | if (!power_monitor->is_system_suspended_) { |
| 177 | power_monitor->is_system_suspended_ = true; |
| 178 | power_monitor->last_system_resume_time_ = TimeTicks::Max(); |
| 179 | GetInstance()->power_suspend_observers_->Notify( |
| 180 | FROM_HERE, &PowerSuspendObserver::OnSuspend); |
| 181 | } |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 182 | } |
| 183 | |
| 184 | void PowerMonitor::NotifyResume() { |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 185 | DCHECK(IsInitialized()); |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 186 | TRACE_EVENT_INSTANT0("base", "PowerMonitor::NotifyResume", |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 187 | TRACE_EVENT_SCOPE_PROCESS); |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 188 | DVLOG(1) << "Power Resuming"; |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 189 | |
| 190 | TimeTicks resume_time = TimeTicks::Now(); |
| 191 | |
| 192 | PowerMonitor* power_monitor = GetInstance(); |
| 193 | AutoLock auto_lock(power_monitor->is_system_suspended_lock_); |
| 194 | if (power_monitor->is_system_suspended_) { |
| 195 | power_monitor->is_system_suspended_ = false; |
| 196 | power_monitor->last_system_resume_time_ = resume_time; |
| 197 | GetInstance()->power_suspend_observers_->Notify( |
| 198 | FROM_HERE, &PowerSuspendObserver::OnResume); |
| 199 | } |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 200 | } |
| 201 | |
Kaido Kert | 25902c6 | 2024-06-17 17:10:28 -0700 | [diff] [blame^] | 202 | void PowerMonitor::NotifyThermalStateChange( |
| 203 | PowerThermalObserver::DeviceThermalState new_state) { |
| 204 | DCHECK(IsInitialized()); |
| 205 | DVLOG(1) << "ThermalStateChange: " |
| 206 | << PowerMonitorSource::DeviceThermalStateToString(new_state); |
| 207 | |
| 208 | PowerMonitor* power_monitor = GetInstance(); |
| 209 | AutoLock auto_lock(power_monitor->power_thermal_state_lock_); |
| 210 | if (power_monitor->power_thermal_state_ != new_state) { |
| 211 | power_monitor->power_thermal_state_ = new_state; |
| 212 | GetInstance()->thermal_state_observers_->Notify( |
| 213 | FROM_HERE, &PowerThermalObserver::OnThermalStateChange, new_state); |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | void PowerMonitor::NotifySpeedLimitChange(int speed_limit) { |
| 218 | DCHECK(IsInitialized()); |
| 219 | DVLOG(1) << "SpeedLimitChange: " << speed_limit; |
| 220 | |
| 221 | PowerMonitor* power_monitor = GetInstance(); |
| 222 | AutoLock auto_lock(power_monitor->power_thermal_state_lock_); |
| 223 | if (power_monitor->speed_limit_ != speed_limit) { |
| 224 | power_monitor->speed_limit_ = speed_limit; |
| 225 | GetInstance()->thermal_state_observers_->Notify( |
| 226 | FROM_HERE, &PowerThermalObserver::OnSpeedLimitChange, speed_limit); |
| 227 | } |
| 228 | } |
| 229 | |
| 230 | PowerMonitor* PowerMonitor::GetInstance() { |
| 231 | static base::NoDestructor<PowerMonitor> power_monitor; |
| 232 | return power_monitor.get(); |
| 233 | } |
| 234 | |
| 235 | PowerMonitor::PowerMonitor() |
| 236 | : power_state_observers_( |
| 237 | base::MakeRefCounted<ObserverListThreadSafe<PowerStateObserver>>()), |
| 238 | power_suspend_observers_( |
| 239 | base::MakeRefCounted<ObserverListThreadSafe<PowerSuspendObserver>>()), |
| 240 | thermal_state_observers_( |
| 241 | base::MakeRefCounted< |
| 242 | ObserverListThreadSafe<PowerThermalObserver>>()) {} |
| 243 | |
| 244 | PowerMonitor::~PowerMonitor() = default; |
| 245 | |
Andrew Top | 0d1858f | 2019-05-15 22:01:47 -0700 | [diff] [blame] | 246 | } // namespace base |