xref: /aosp_15_r20/external/cronet/base/power_monitor/battery_state_sampler.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 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/power_monitor/battery_state_sampler.h"
6 
7 #include "base/power_monitor/power_monitor_buildflags.h"
8 
9 #if !BUILDFLAG(IS_MAC)
10 #include "base/power_monitor/timer_sampling_event_source.h"
11 #endif
12 
13 namespace base {
14 
15 namespace {
16 
17 // Singleton instance of the BatteryStateSampler.
18 BatteryStateSampler* g_battery_state_sampler = nullptr;
19 bool g_test_instance_installed = false;
20 
21 }  // namespace
22 
BatteryStateSampler(std::unique_ptr<SamplingEventSource> sampling_event_source,std::unique_ptr<BatteryLevelProvider> battery_level_provider)23 BatteryStateSampler::BatteryStateSampler(
24     std::unique_ptr<SamplingEventSource> sampling_event_source,
25     std::unique_ptr<BatteryLevelProvider> battery_level_provider)
26     : sampling_event_source_(std::move(sampling_event_source)),
27       battery_level_provider_(std::move(battery_level_provider)) {
28   DCHECK(sampling_event_source_);
29   DCHECK(battery_level_provider_);
30 
31   DCHECK(!g_battery_state_sampler);
32   g_battery_state_sampler = this;
33 
34   // Get an initial sample.
35   battery_level_provider_->GetBatteryState(
36       base::BindOnce(&BatteryStateSampler::OnInitialBatteryStateSampled,
37                      base::Unretained(this)));
38 
39   // Start the periodic sampling.
40   sampling_event_source_->Start(base::BindRepeating(
41       &BatteryStateSampler::OnSamplingEvent, base::Unretained(this)));
42 }
43 
~BatteryStateSampler()44 BatteryStateSampler::~BatteryStateSampler() {
45   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
46   DCHECK_EQ(g_battery_state_sampler, this);
47   g_battery_state_sampler = nullptr;
48   g_test_instance_installed = false;
49 }
50 
51 // static
Get()52 BatteryStateSampler* BatteryStateSampler::Get() {
53   // On a platform with a BatteryLevelProvider implementation, the global
54   // instance must be created before accessing it.
55   // TODO(crbug.com/1373560): ChromeOS currently doesn't define
56   // `HAS_BATTERY_LEVEL_PROVIDER_IMPL` but it should once the locations of the
57   // providers and sampling sources are consolidated.
58 #if BUILDFLAG(HAS_BATTERY_LEVEL_PROVIDER_IMPL) || BUILDFLAG(IS_CHROMEOS_ASH)
59   DCHECK(g_battery_state_sampler);
60 #endif
61   return g_battery_state_sampler;
62 }
63 
AddObserver(Observer * observer)64 void BatteryStateSampler::AddObserver(Observer* observer) {
65   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
66 
67   observer_list_.AddObserver(observer);
68 
69   // Send the last sample available.
70   if (has_last_battery_state_)
71     observer->OnBatteryStateSampled(last_battery_state_);
72 }
73 
RemoveObserver(Observer * observer)74 void BatteryStateSampler::RemoveObserver(Observer* observer) {
75   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
76   observer_list_.RemoveObserver(observer);
77 }
78 
Shutdown()79 void BatteryStateSampler::Shutdown() {
80   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
81   sampling_event_source_.reset();
82   battery_level_provider_.reset();
83 }
84 
85 // static
86 std::unique_ptr<base::BatteryStateSampler>
CreateInstanceForTesting(std::unique_ptr<SamplingEventSource> sampling_event_source,std::unique_ptr<BatteryLevelProvider> battery_level_provider)87 BatteryStateSampler::CreateInstanceForTesting(
88     std::unique_ptr<SamplingEventSource> sampling_event_source,
89     std::unique_ptr<BatteryLevelProvider> battery_level_provider) {
90   g_test_instance_installed = true;
91   return std::make_unique<BatteryStateSampler>(
92       std::move(sampling_event_source), std::move(battery_level_provider));
93 }
94 
95 // static
HasTestingInstance()96 bool BatteryStateSampler::HasTestingInstance() {
97   return g_test_instance_installed;
98 }
99 
100 #if !BUILDFLAG(IS_MAC)
101 // static
102 std::unique_ptr<SamplingEventSource>
CreateSamplingEventSource()103 BatteryStateSampler::CreateSamplingEventSource() {
104   // On platforms where the OS does not provide a notification when an updated
105   // battery level is available, simply sample on a regular 1 minute interval.
106   return std::make_unique<TimerSamplingEventSource>(Minutes(1));
107 }
108 #endif  // !BUILDFLAG(IS_MAC)
109 
OnInitialBatteryStateSampled(const std::optional<BatteryLevelProvider::BatteryState> & battery_state)110 void BatteryStateSampler::OnInitialBatteryStateSampled(
111     const std::optional<BatteryLevelProvider::BatteryState>& battery_state) {
112   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
113 
114   DCHECK(!has_last_battery_state_);
115   has_last_battery_state_ = true;
116   last_battery_state_ = battery_state;
117 
118   for (auto& observer : observer_list_)
119     observer.OnBatteryStateSampled(battery_state);
120 }
121 
OnSamplingEvent()122 void BatteryStateSampler::OnSamplingEvent() {
123   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
124   DCHECK(battery_level_provider_);
125 
126   battery_level_provider_->GetBatteryState(base::BindOnce(
127       &BatteryStateSampler::OnBatteryStateSampled, base::Unretained(this)));
128 }
129 
OnBatteryStateSampled(const std::optional<BatteryLevelProvider::BatteryState> & battery_state)130 void BatteryStateSampler::OnBatteryStateSampled(
131     const std::optional<BatteryLevelProvider::BatteryState>& battery_state) {
132   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
133 
134   DCHECK(has_last_battery_state_);
135   last_battery_state_ = battery_state;
136 
137   for (auto& observer : observer_list_)
138     observer.OnBatteryStateSampled(battery_state);
139 }
140 
141 }  // namespace base
142