blob: a5f41763683326ea72dd9d480a4198337bc8856e [file] [log] [blame]
Kaido Kert25902c62024-06-17 17:10:28 -07001// Copyright 2013 The Chromium Authors
Andrew Top0d1858f2019-05-15 22:01:47 -07002// 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 Kert25902c62024-06-17 17:10:28 -07009#include "base/logging.h"
10#include "base/no_destructor.h"
Andrew Top0d1858f2019-05-15 22:01:47 -070011#include "base/power_monitor/power_monitor_source.h"
Kaido Kert25902c62024-06-17 17:10:28 -070012#include "base/trace_event/base_tracing.h"
13#include "build/build_config.h"
Andrew Top0d1858f2019-05-15 22:01:47 -070014
15namespace base {
16
Kaido Kert25902c62024-06-17 17:10:28 -070017void PowerMonitor::Initialize(std::unique_ptr<PowerMonitorSource> source) {
18 DCHECK(!IsInitialized());
19 PowerMonitor* power_monitor = GetInstance();
20 power_monitor->source_ = std::move(source);
Andrew Top0d1858f2019-05-15 22:01:47 -070021
Kaido Kert25902c62024-06-17 17:10:28 -070022 // 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 Top0d1858f2019-05-15 22:01:47 -070032}
33
Kaido Kert25902c62024-06-17 17:10:28 -070034bool PowerMonitor::IsInitialized() {
35 return GetInstance()->source_.get() != nullptr;
Andrew Top0d1858f2019-05-15 22:01:47 -070036}
37
38// static
Kaido Kert25902c62024-06-17 17:10:28 -070039void PowerMonitor::AddPowerSuspendObserver(PowerSuspendObserver* obs) {
40 GetInstance()->power_suspend_observers_->AddObserver(obs);
Andrew Top0d1858f2019-05-15 22:01:47 -070041}
42
Kaido Kert25902c62024-06-17 17:10:28 -070043// static
44void PowerMonitor::RemovePowerSuspendObserver(PowerSuspendObserver* obs) {
45 GetInstance()->power_suspend_observers_->RemoveObserver(obs);
Andrew Top0d1858f2019-05-15 22:01:47 -070046}
47
Kaido Kert25902c62024-06-17 17:10:28 -070048// static
49void PowerMonitor::AddPowerStateObserver(PowerStateObserver* obs) {
50 GetInstance()->power_state_observers_->AddObserver(obs);
51}
52
53// static
54void PowerMonitor::RemovePowerStateObserver(PowerStateObserver* obs) {
55 GetInstance()->power_state_observers_->RemoveObserver(obs);
56}
57
58// static
59void PowerMonitor::AddPowerThermalObserver(PowerThermalObserver* obs) {
60 GetInstance()->thermal_state_observers_->AddObserver(obs);
61}
62
63// static
64void PowerMonitor::RemovePowerThermalObserver(PowerThermalObserver* obs) {
65 GetInstance()->thermal_state_observers_->RemoveObserver(obs);
66}
67
68// static
69bool 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
78bool 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
87PowerThermalObserver::DeviceThermalState
88PowerMonitor::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 Top0d1858f2019-05-15 22:01:47 -070094}
95
96PowerMonitorSource* PowerMonitor::Source() {
Kaido Kert25902c62024-06-17 17:10:28 -070097 return GetInstance()->source_.get();
Andrew Top0d1858f2019-05-15 22:01:47 -070098}
99
100bool PowerMonitor::IsOnBatteryPower() {
Kaido Kert25902c62024-06-17 17:10:28 -0700101 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 Top0d1858f2019-05-15 22:01:47 -0700105}
106
Kaido Kert25902c62024-06-17 17:10:28 -0700107TimeTicks 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
113void 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
134PowerThermalObserver::DeviceThermalState
135PowerMonitor::GetCurrentThermalState() {
136 DCHECK(IsInitialized());
137 return GetInstance()->source_->GetCurrentThermalState();
138}
139
140// static
141void PowerMonitor::SetCurrentThermalState(
142 PowerThermalObserver::DeviceThermalState state) {
143 DCHECK(IsInitialized());
144 GetInstance()->source_->SetCurrentThermalState(state);
145}
146
147#if BUILDFLAG(IS_ANDROID)
148int PowerMonitor::GetRemainingBatteryCapacity() {
149 DCHECK(IsInitialized());
150 return PowerMonitor::Source()->GetRemainingBatteryCapacity();
151}
152#endif // BUILDFLAG(IS_ANDROID)
153
154void PowerMonitor::NotifyPowerStateChange(bool on_battery_power) {
155 DCHECK(IsInitialized());
156 DVLOG(1) << "PowerStateChange: " << (on_battery_power ? "On" : "Off")
Andrew Top0d1858f2019-05-15 22:01:47 -0700157 << " battery";
Kaido Kert25902c62024-06-17 17:10:28 -0700158
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 Top0d1858f2019-05-15 22:01:47 -0700166}
167
168void PowerMonitor::NotifySuspend() {
Kaido Kert25902c62024-06-17 17:10:28 -0700169 DCHECK(IsInitialized());
Andrew Top0d1858f2019-05-15 22:01:47 -0700170 TRACE_EVENT_INSTANT0("base", "PowerMonitor::NotifySuspend",
Kaido Kert25902c62024-06-17 17:10:28 -0700171 TRACE_EVENT_SCOPE_PROCESS);
Andrew Top0d1858f2019-05-15 22:01:47 -0700172 DVLOG(1) << "Power Suspending";
Kaido Kert25902c62024-06-17 17:10:28 -0700173
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 Top0d1858f2019-05-15 22:01:47 -0700182}
183
184void PowerMonitor::NotifyResume() {
Kaido Kert25902c62024-06-17 17:10:28 -0700185 DCHECK(IsInitialized());
Andrew Top0d1858f2019-05-15 22:01:47 -0700186 TRACE_EVENT_INSTANT0("base", "PowerMonitor::NotifyResume",
Kaido Kert25902c62024-06-17 17:10:28 -0700187 TRACE_EVENT_SCOPE_PROCESS);
Andrew Top0d1858f2019-05-15 22:01:47 -0700188 DVLOG(1) << "Power Resuming";
Kaido Kert25902c62024-06-17 17:10:28 -0700189
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 Top0d1858f2019-05-15 22:01:47 -0700200}
201
Kaido Kert25902c62024-06-17 17:10:28 -0700202void 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
217void 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
230PowerMonitor* PowerMonitor::GetInstance() {
231 static base::NoDestructor<PowerMonitor> power_monitor;
232 return power_monitor.get();
233}
234
235PowerMonitor::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
244PowerMonitor::~PowerMonitor() = default;
245
Andrew Top0d1858f2019-05-15 22:01:47 -0700246} // namespace base