blob: 9a572c0b952be797daf780379600693de81bf079 [file] [log] [blame] [edit]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/power_monitor/power_monitor.h"
#include <utility>
#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/power_monitor/power_monitor_source.h"
#include "base/trace_event/base_tracing.h"
#include "build/build_config.h"
#include "power_observer.h"
namespace base {
void PowerMonitor::Initialize(std::unique_ptr<PowerMonitorSource> source) {
DCHECK(!IsInitialized());
source_ = std::move(source);
// When a power source is associated with the power monitor, ensure the
// initial state is propagated to observers, if needed.
NotifyPowerStateChange(Source()->GetBatteryPowerStatus());
NotifyThermalStateChange(Source()->GetCurrentThermalState());
NotifySpeedLimitChange(Source()->GetInitialSpeedLimit());
}
bool PowerMonitor::IsInitialized() const {
return source_ != nullptr;
}
void PowerMonitor::AddPowerSuspendObserver(PowerSuspendObserver* obs) {
power_suspend_observers_->AddObserver(obs);
}
void PowerMonitor::RemovePowerSuspendObserver(PowerSuspendObserver* obs) {
power_suspend_observers_->RemoveObserver(obs);
}
void PowerMonitor::AddPowerStateObserver(PowerStateObserver* obs) {
power_state_observers_->AddObserver(obs);
}
void PowerMonitor::RemovePowerStateObserver(PowerStateObserver* obs) {
power_state_observers_->RemoveObserver(obs);
}
void PowerMonitor::AddPowerThermalObserver(PowerThermalObserver* obs) {
thermal_state_observers_->AddObserver(obs);
}
void PowerMonitor::RemovePowerThermalObserver(PowerThermalObserver* obs) {
thermal_state_observers_->RemoveObserver(obs);
}
bool PowerMonitor::AddPowerSuspendObserverAndReturnSuspendedState(
PowerSuspendObserver* obs) {
AutoLock auto_lock(is_system_suspended_lock_);
power_suspend_observers_->AddObserver(obs);
return is_system_suspended_;
}
// static
bool PowerMonitor::AddPowerStateObserverAndReturnOnBatteryState(
PowerStateObserver* obs) {
return AddPowerStateObserverAndReturnBatteryPowerStatus(obs) ==
PowerStateObserver::BatteryPowerStatus::kBatteryPower;
}
PowerStateObserver::BatteryPowerStatus
PowerMonitor::AddPowerStateObserverAndReturnBatteryPowerStatus(
PowerStateObserver* obs) {
AutoLock auto_lock(battery_power_status_lock_);
power_state_observers_->AddObserver(obs);
return battery_power_status_;
}
// static
PowerThermalObserver::DeviceThermalState
PowerMonitor::AddPowerStateObserverAndReturnPowerThermalState(
PowerThermalObserver* obs) {
AutoLock auto_lock(power_thermal_state_lock_);
thermal_state_observers_->AddObserver(obs);
return power_thermal_state_;
}
const PowerMonitorSource* PowerMonitor::Source() const {
return source_.get();
}
bool PowerMonitor::IsOnBatteryPower() const {
DCHECK(IsInitialized());
return GetBatteryPowerStatus() ==
PowerStateObserver::BatteryPowerStatus::kBatteryPower;
}
PowerStateObserver::BatteryPowerStatus PowerMonitor::GetBatteryPowerStatus()
const {
DCHECK(IsInitialized());
AutoLock auto_lock(battery_power_status_lock_);
return battery_power_status_;
}
TimeTicks PowerMonitor::GetLastSystemResumeTime() const {
AutoLock auto_lock(is_system_suspended_lock_);
return last_system_resume_time_;
}
void PowerMonitor::ShutdownForTesting() {
source_ = nullptr;
{
AutoLock auto_lock(is_system_suspended_lock_);
is_system_suspended_ = false;
last_system_resume_time_ = TimeTicks();
}
{
AutoLock auto_lock(battery_power_status_lock_);
battery_power_status_ = PowerStateObserver::BatteryPowerStatus::kUnknown;
}
{
AutoLock auto_lock(power_thermal_state_lock_);
power_thermal_state_ = PowerThermalObserver::DeviceThermalState::kUnknown;
}
}
// static
PowerThermalObserver::DeviceThermalState PowerMonitor::GetCurrentThermalState()
const {
DCHECK(IsInitialized());
return source_->GetCurrentThermalState();
}
// static
void PowerMonitor::SetCurrentThermalState(
PowerThermalObserver::DeviceThermalState state) {
DCHECK(IsInitialized());
source_->SetCurrentThermalState(state);
}
#if BUILDFLAG(IS_ANDROID)
int PowerMonitor::GetRemainingBatteryCapacity() const {
DCHECK(IsInitialized());
return Source()->GetRemainingBatteryCapacity();
}
#endif // BUILDFLAG(IS_ANDROID)
void PowerMonitor::NotifyPowerStateChange(bool on_battery_power) {
DCHECK(IsInitialized());
NotifyPowerStateChange(
on_battery_power
? PowerStateObserver::BatteryPowerStatus::kBatteryPower
: PowerStateObserver::BatteryPowerStatus::kExternalPower);
}
void PowerMonitor::NotifyPowerStateChange(
PowerStateObserver::BatteryPowerStatus battery_power_status) {
DCHECK(IsInitialized());
if (battery_power_status ==
PowerStateObserver::BatteryPowerStatus::kUnknown) {
DVLOG(1) << "PowerStateChange: with unknown value";
} else {
DVLOG(1) << "PowerStateChange: "
<< (battery_power_status ==
PowerStateObserver::BatteryPowerStatus::kBatteryPower
? "On"
: "Off")
<< " battery";
TRACE_EVENT_INSTANT(
"power",
battery_power_status ==
PowerStateObserver::BatteryPowerStatus::kBatteryPower
? perfetto::StaticString("PowerMonitor::BatteryPower")
: perfetto::StaticString("PowerMonitor::ExternalPower"),
process_track_);
}
AutoLock auto_lock(battery_power_status_lock_);
if (battery_power_status_ != battery_power_status) {
battery_power_status_ = battery_power_status;
power_state_observers_->Notify(
FROM_HERE, &PowerStateObserver::OnBatteryPowerStatusChange,
battery_power_status);
}
}
void PowerMonitor::NotifySuspend() {
DCHECK(IsInitialized());
TRACE_EVENT_INSTANT("power", "PowerMonitor::NotifySuspend", process_track_);
DVLOG(1) << "Power Suspending";
AutoLock auto_lock(is_system_suspended_lock_);
if (!is_system_suspended_) {
is_system_suspended_ = true;
last_system_resume_time_ = TimeTicks::Max();
power_suspend_observers_->Notify(FROM_HERE,
&PowerSuspendObserver::OnSuspend);
}
}
void PowerMonitor::NotifyResume() {
DCHECK(IsInitialized());
TRACE_EVENT_INSTANT("power", "PowerMonitor::NotifyResume", process_track_);
DVLOG(1) << "Power Resuming";
TimeTicks resume_time = TimeTicks::Now();
AutoLock auto_lock(is_system_suspended_lock_);
if (is_system_suspended_) {
is_system_suspended_ = false;
last_system_resume_time_ = resume_time;
power_suspend_observers_->Notify(FROM_HERE,
&PowerSuspendObserver::OnResume);
}
}
void PowerMonitor::NotifyThermalStateChange(
PowerThermalObserver::DeviceThermalState new_state) {
DCHECK(IsInitialized());
DVLOG(1) << "ThermalStateChange: "
<< PowerMonitorSource::DeviceThermalStateToString(new_state);
AutoLock auto_lock(power_thermal_state_lock_);
if (power_thermal_state_ != new_state) {
power_thermal_state_ = new_state;
thermal_state_observers_->Notify(
FROM_HERE, &PowerThermalObserver::OnThermalStateChange, new_state);
}
}
void PowerMonitor::NotifySpeedLimitChange(int speed_limit) {
DCHECK(IsInitialized());
DVLOG(1) << "SpeedLimitChange: " << speed_limit;
AutoLock auto_lock(power_thermal_state_lock_);
if (speed_limit_ != speed_limit) {
speed_limit_ = speed_limit;
thermal_state_observers_->Notify(
FROM_HERE, &PowerThermalObserver::OnSpeedLimitChange, speed_limit);
}
}
PowerMonitor* PowerMonitor::GetInstance() {
static base::NoDestructor<PowerMonitor> power_monitor;
return power_monitor.get();
}
PowerMonitor::PowerMonitor()
: process_track_("PowerMonitor"),
power_state_observers_(
base::MakeRefCounted<ObserverListThreadSafe<PowerStateObserver>>()),
power_suspend_observers_(
base::MakeRefCounted<ObserverListThreadSafe<PowerSuspendObserver>>()),
thermal_state_observers_(
base::MakeRefCounted<
ObserverListThreadSafe<PowerThermalObserver>>()) {}
PowerMonitor::~PowerMonitor() = default;
} // namespace base