Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: device/battery/battery_status_manager_win.cc

Issue 2818673003: [DeviceService] Expose battery monitoring solely via the Device Service (Closed)
Patch Set: Java file format change Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
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 "device/battery/battery_status_manager_win.h"
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/macros.h"
11 #include "base/metrics/histogram_macros.h"
12 #include "base/strings/string16.h"
13 #include "base/win/message_window.h"
14 #include "base/win/windows_version.h"
15 #include "device/battery/battery_status_manager.h"
16
17 namespace device {
18
19 namespace {
20
21 typedef BatteryStatusService::BatteryUpdateCallback BatteryCallback;
22
23 const wchar_t kWindowClassName[] = L"BatteryStatusMessageWindow";
24
25 // This enum is used for histogram. Don't change the order of the existing
26 // values.
27 enum NumberBatteriesType {
28 UNKNOWN_BATTERIES = 0,
29 NO_BATTERY = 1,
30 ONE_OR_MORE_BATTERIES = 2,
31 BATTERY_TYPES_COUNT = 3,
32 };
33
34 void UpdateNumberBatteriesHistogram(NumberBatteriesType count) {
35 UMA_HISTOGRAM_ENUMERATION("BatteryStatus.NumberBatteriesWin",
36 count,
37 BATTERY_TYPES_COUNT);
38 }
39
40 void UpdateNumberBatteriesHistogram() {
41 SYSTEM_POWER_STATUS win_status;
42 if (!GetSystemPowerStatus(&win_status)) {
43 UpdateNumberBatteriesHistogram(UNKNOWN_BATTERIES);
44 return;
45 }
46
47 if (win_status.BatteryFlag == 255)
48 UpdateNumberBatteriesHistogram(UNKNOWN_BATTERIES);
49 else if (win_status.BatteryFlag == 128)
50 UpdateNumberBatteriesHistogram(NO_BATTERY);
51 else
52 UpdateNumberBatteriesHistogram(ONE_OR_MORE_BATTERIES);
53 }
54
55 // Message-only window for handling battery changes on Windows.
56 class BatteryStatusObserver {
57 public:
58 explicit BatteryStatusObserver(const BatteryCallback& callback)
59 : power_handle_(NULL),
60 battery_change_handle_(NULL),
61 callback_(callback) {
62 }
63
64 ~BatteryStatusObserver() { DCHECK(!window_); }
65
66 void Start() {
67 if (CreateMessageWindow()) {
68 BatteryChanged();
69 // RegisterPowerSettingNotification function work from Windows Vista
70 // onwards. However even without them we will receive notifications,
71 // e.g. when a power source is connected.
72 // TODO(timvolodine) : consider polling for battery changes on windows
73 // versions prior to Vista, see crbug.com/402466.
74 power_handle_ =
75 RegisterNotification(&GUID_ACDC_POWER_SOURCE);
76 battery_change_handle_ =
77 RegisterNotification(&GUID_BATTERY_PERCENTAGE_REMAINING);
78 } else {
79 // Could not create a message window, execute callback with the default
80 // values.
81 callback_.Run(mojom::BatteryStatus());
82 }
83
84 UpdateNumberBatteriesHistogram();
85 }
86
87 void Stop() {
88 if (power_handle_) {
89 UnregisterNotification(power_handle_);
90 power_handle_ = NULL;
91 }
92 if (battery_change_handle_) {
93 UnregisterNotification(battery_change_handle_);
94 battery_change_handle_ = NULL;
95 }
96 window_.reset();
97 }
98
99 private:
100 void BatteryChanged() {
101 SYSTEM_POWER_STATUS win_status;
102 if (GetSystemPowerStatus(&win_status))
103 callback_.Run(ComputeWebBatteryStatus(win_status));
104 else
105 callback_.Run(mojom::BatteryStatus());
106 }
107
108 bool HandleMessage(UINT message,
109 WPARAM wparam,
110 LPARAM lparam,
111 LRESULT* result) {
112 switch(message) {
113 case WM_POWERBROADCAST:
114 if (wparam == PBT_APMPOWERSTATUSCHANGE ||
115 wparam == PBT_POWERSETTINGCHANGE) {
116 BatteryChanged();
117 }
118 *result = NULL;
119 return true;
120 default:
121 return false;
122 }
123 }
124
125 HPOWERNOTIFY RegisterNotification(LPCGUID power_setting) {
126 if (base::win::GetVersion() < base::win::VERSION_VISTA)
127 return NULL;
128
129 return RegisterPowerSettingNotification(window_->hwnd(), power_setting,
130 DEVICE_NOTIFY_WINDOW_HANDLE);
131 }
132
133 BOOL UnregisterNotification(HPOWERNOTIFY handle) {
134 if (base::win::GetVersion() < base::win::VERSION_VISTA)
135 return FALSE;
136
137 return UnregisterPowerSettingNotification(handle);
138 }
139
140 bool CreateMessageWindow() {
141 // TODO(timvolodine): consider reusing the message window of PowerMonitor.
142 window_.reset(new base::win::MessageWindow());
143 if (!window_->CreateNamed(base::Bind(&BatteryStatusObserver::HandleMessage,
144 base::Unretained(this)),
145 base::string16(kWindowClassName))) {
146 LOG(ERROR) << "Failed to create message window: " << kWindowClassName;
147 window_.reset();
148 return false;
149 }
150 return true;
151 }
152
153 HPOWERNOTIFY power_handle_;
154 HPOWERNOTIFY battery_change_handle_;
155 BatteryCallback callback_;
156 std::unique_ptr<base::win::MessageWindow> window_;
157
158 DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver);
159 };
160
161 class BatteryStatusManagerWin : public BatteryStatusManager {
162 public:
163 explicit BatteryStatusManagerWin(const BatteryCallback& callback)
164 : battery_observer_(new BatteryStatusObserver(callback)) {}
165 ~BatteryStatusManagerWin() override { battery_observer_->Stop(); }
166
167 public:
168 // BatteryStatusManager:
169 bool StartListeningBatteryChange() override {
170 battery_observer_->Start();
171 return true;
172 }
173
174 void StopListeningBatteryChange() override { battery_observer_->Stop(); }
175
176 private:
177 std::unique_ptr<BatteryStatusObserver> battery_observer_;
178
179 DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerWin);
180 };
181
182 } // namespace
183
184 mojom::BatteryStatus ComputeWebBatteryStatus(
185 const SYSTEM_POWER_STATUS& win_status) {
186 mojom::BatteryStatus status;
187 status.charging = win_status.ACLineStatus != WIN_AC_LINE_STATUS_OFFLINE;
188
189 // Set level if available. Otherwise keep the default value which is 1.
190 if (win_status.BatteryLifePercent != 255) {
191 // Convert percentage to a value between 0 and 1 with 2 significant digits.
192 status.level = static_cast<double>(win_status.BatteryLifePercent) / 100.;
193 }
194
195 if (!status.charging) {
196 // Set discharging_time if available otherwise keep the default value,
197 // which is +Infinity.
198 if (win_status.BatteryLifeTime != (DWORD)-1)
199 status.discharging_time = win_status.BatteryLifeTime;
200 status.charging_time = std::numeric_limits<double>::infinity();
201 } else {
202 // Set charging_time to +Infinity if not fully charged, otherwise leave the
203 // default value, which is 0.
204 if (status.level < 1)
205 status.charging_time = std::numeric_limits<double>::infinity();
206 }
207 return status;
208 }
209
210 // static
211 std::unique_ptr<BatteryStatusManager> BatteryStatusManager::Create(
212 const BatteryStatusService::BatteryUpdateCallback& callback) {
213 return std::unique_ptr<BatteryStatusManager>(
214 new BatteryStatusManagerWin(callback));
215 }
216
217 } // namespace device
OLDNEW
« no previous file with comments | « device/battery/battery_status_manager_win.h ('k') | device/battery/battery_status_manager_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698