// Copyright 2022 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/battery_state_sampler.h" #include "base/power_monitor/power_monitor_buildflags.h" #if !BUILDFLAG(IS_MAC) #include "base/power_monitor/timer_sampling_event_source.h" #endif namespace base { namespace { // Singleton instance of the BatteryStateSampler. BatteryStateSampler* g_battery_state_sampler = nullptr; bool g_test_instance_installed = false; } // namespace BatteryStateSampler::BatteryStateSampler( std::unique_ptr sampling_event_source, std::unique_ptr battery_level_provider) : sampling_event_source_(std::move(sampling_event_source)), battery_level_provider_(std::move(battery_level_provider)) { DCHECK(sampling_event_source_); DCHECK(battery_level_provider_); DCHECK(!g_battery_state_sampler); g_battery_state_sampler = this; // Get an initial sample. battery_level_provider_->GetBatteryState( base::BindOnce(&BatteryStateSampler::OnInitialBatteryStateSampled, base::Unretained(this))); // Start the periodic sampling. sampling_event_source_->Start(base::BindRepeating( &BatteryStateSampler::OnSamplingEvent, base::Unretained(this))); } BatteryStateSampler::~BatteryStateSampler() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_EQ(g_battery_state_sampler, this); g_battery_state_sampler = nullptr; g_test_instance_installed = false; } // static BatteryStateSampler* BatteryStateSampler::Get() { // On a platform with a BatteryLevelProvider implementation, the global // instance must be created before accessing it. // TODO(crbug.com/1373560): ChromeOS currently doesn't define // `HAS_BATTERY_LEVEL_PROVIDER_IMPL` but it should once the locations of the // providers and sampling sources are consolidated. #if BUILDFLAG(HAS_BATTERY_LEVEL_PROVIDER_IMPL) || BUILDFLAG(IS_CHROMEOS_ASH) DCHECK(g_battery_state_sampler); #endif return g_battery_state_sampler; } void BatteryStateSampler::AddObserver(Observer* observer) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); observer_list_.AddObserver(observer); // Send the last sample available. if (has_last_battery_state_) observer->OnBatteryStateSampled(last_battery_state_); } void BatteryStateSampler::RemoveObserver(Observer* observer) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); observer_list_.RemoveObserver(observer); } void BatteryStateSampler::Shutdown() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); sampling_event_source_.reset(); battery_level_provider_.reset(); } // static std::unique_ptr BatteryStateSampler::CreateInstanceForTesting( std::unique_ptr sampling_event_source, std::unique_ptr battery_level_provider) { g_test_instance_installed = true; return std::make_unique( std::move(sampling_event_source), std::move(battery_level_provider)); } // static bool BatteryStateSampler::HasTestingInstance() { return g_test_instance_installed; } #if !BUILDFLAG(IS_MAC) // static std::unique_ptr BatteryStateSampler::CreateSamplingEventSource() { // On platforms where the OS does not provide a notification when an updated // battery level is available, simply sample on a regular 1 minute interval. return std::make_unique(Minutes(1)); } #endif // !BUILDFLAG(IS_MAC) void BatteryStateSampler::OnInitialBatteryStateSampled( const absl::optional& battery_state) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!has_last_battery_state_); has_last_battery_state_ = true; last_battery_state_ = battery_state; for (auto& observer : observer_list_) observer.OnBatteryStateSampled(battery_state); } void BatteryStateSampler::OnSamplingEvent() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(battery_level_provider_); battery_level_provider_->GetBatteryState(base::BindOnce( &BatteryStateSampler::OnBatteryStateSampled, base::Unretained(this))); } void BatteryStateSampler::OnBatteryStateSampled( const absl::optional& battery_state) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(has_last_battery_state_); last_battery_state_ = battery_state; for (auto& observer : observer_list_) observer.OnBatteryStateSampled(battery_state); } } // namespace base