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

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

Issue 457933002: Replace Chrome IPC with Mojo IPC for querying BatteryStatus service Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/battery_status/battery_status_manager.h" 5 #include "device/battery/battery_status_manager.h"
6 6
7 #include <CoreFoundation/CoreFoundation.h> 7 #include <CoreFoundation/CoreFoundation.h>
8 #include <IOKit/ps/IOPowerSources.h> 8 #include <IOKit/ps/IOPowerSources.h>
9 #include <IOKit/ps/IOPSKeys.h> 9 #include <IOKit/ps/IOPSKeys.h>
10 #include <vector> 10 #include <vector>
11 11
12 #include "base/mac/foundation_util.h" 12 #include "base/mac/foundation_util.h"
13 #include "base/mac/scoped_cftyperef.h" 13 #include "base/mac/scoped_cftyperef.h"
14 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted.h"
15 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
16 #include "base/time/time.h" 16 #include "base/time/time.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "third_party/WebKit/public/platform/WebBatteryStatus.h"
19 17
20 namespace content { 18 namespace device {
21 19
22 namespace { 20 namespace {
23 21
24 typedef BatteryStatusService::BatteryUpdateCallback BatteryCallback; 22 typedef BatteryStatusService::BatteryUpdateCallback BatteryCallback;
25 23
26 // Returns the value corresponding to |key| in the dictionary |description|. 24 // Returns the value corresponding to |key| in the dictionary |description|.
27 // Returns |default_value| if the dictionary does not contain |key|, the 25 // Returns |default_value| if the dictionary does not contain |key|, the
28 // corresponding value is NULL or it could not be converted to SInt64. 26 // corresponding value is NULL or it could not be converted to SInt64.
29 SInt64 GetValueAsSInt64(CFDictionaryRef description, 27 SInt64 GetValueAsSInt64(CFDictionaryRef description,
30 CFStringRef key, 28 CFStringRef key,
(...skipping 21 matching lines...) Expand all
52 if (!string1 || !string2) 50 if (!string1 || !string2)
53 return false; 51 return false;
54 return CFStringCompare(string1, string2, 0) == kCFCompareEqualTo; 52 return CFStringCompare(string1, string2, 0) == kCFCompareEqualTo;
55 } 53 }
56 54
57 void UpdateNumberBatteriesHistogram(int count) { 55 void UpdateNumberBatteriesHistogram(int count) {
58 UMA_HISTOGRAM_CUSTOM_COUNTS( 56 UMA_HISTOGRAM_CUSTOM_COUNTS(
59 "BatteryStatus.NumberBatteriesMac", count, 1, 5, 6); 57 "BatteryStatus.NumberBatteriesMac", count, 1, 5, 6);
60 } 58 }
61 59
62 void FetchBatteryStatus(CFDictionaryRef description, 60 void FetchBatteryStatus(CFDictionaryRef description, BatteryStatus* status) {
63 blink::WebBatteryStatus& status) {
64 CFStringRef current_state = 61 CFStringRef current_state =
65 base::mac::GetValueFromDictionary<CFStringRef>(description, 62 base::mac::GetValueFromDictionary<CFStringRef>(description,
66 CFSTR(kIOPSPowerSourceStateKey)); 63 CFSTR(kIOPSPowerSourceStateKey));
67 64
68 bool on_battery_power = 65 bool on_battery_power =
69 CFStringsAreEqual(current_state, CFSTR(kIOPSBatteryPowerValue)); 66 CFStringsAreEqual(current_state, CFSTR(kIOPSBatteryPowerValue));
70 bool is_charging = 67 bool is_charging =
71 GetValueAsBoolean(description, CFSTR(kIOPSIsChargingKey), true); 68 GetValueAsBoolean(description, CFSTR(kIOPSIsChargingKey), true);
72 bool is_charged = 69 bool is_charged =
73 GetValueAsBoolean(description, CFSTR(kIOPSIsChargedKey), false); 70 GetValueAsBoolean(description, CFSTR(kIOPSIsChargedKey), false);
74 71
75 status.charging = !on_battery_power || is_charging; 72 status->charging = !on_battery_power || is_charging;
76 73
77 SInt64 current_capacity = 74 SInt64 current_capacity =
78 GetValueAsSInt64(description, CFSTR(kIOPSCurrentCapacityKey), -1); 75 GetValueAsSInt64(description, CFSTR(kIOPSCurrentCapacityKey), -1);
79 SInt64 max_capacity = 76 SInt64 max_capacity =
80 GetValueAsSInt64(description, CFSTR(kIOPSMaxCapacityKey), -1); 77 GetValueAsSInt64(description, CFSTR(kIOPSMaxCapacityKey), -1);
81 78
82 // Set level if it is available and valid. Otherwise leave the default value, 79 // Set level if it is available and valid. Otherwise leave the default value,
83 // which is 1. 80 // which is 1.
84 if (current_capacity != -1 && max_capacity != -1 && 81 if (current_capacity != -1 && max_capacity != -1 &&
85 current_capacity <= max_capacity && max_capacity != 0) { 82 current_capacity <= max_capacity && max_capacity != 0) {
86 status.level = current_capacity / static_cast<double>(max_capacity); 83 status->level = current_capacity / static_cast<double>(max_capacity);
87 } 84 }
88 85
89 if (is_charging) { 86 if (is_charging) {
90 SInt64 charging_time = 87 SInt64 charging_time =
91 GetValueAsSInt64(description, CFSTR(kIOPSTimeToFullChargeKey), -1); 88 GetValueAsSInt64(description, CFSTR(kIOPSTimeToFullChargeKey), -1);
92 89
93 // Battery is charging: set the charging time if it's available, otherwise 90 // Battery is charging: set the charging time if it's available, otherwise
94 // set to +infinity. 91 // set to +infinity.
95 status.chargingTime = charging_time != -1 92 status->charging_time = charging_time != -1
96 ? base::TimeDelta::FromMinutes(charging_time).InSeconds() 93 ? base::TimeDelta::FromMinutes(charging_time).InSeconds()
97 : std::numeric_limits<double>::infinity(); 94 : std::numeric_limits<double>::infinity();
98 } else { 95 } else {
99 // Battery is not charging. 96 // Battery is not charging.
100 // Set chargingTime to +infinity if the battery is not charged. Otherwise 97 // Set chargingTime to +infinity if the battery is not charged. Otherwise
101 // leave the default value, which is 0. 98 // leave the default value, which is 0.
102 if (!is_charged) 99 if (!is_charged)
103 status.chargingTime = std::numeric_limits<double>::infinity(); 100 status->charging_time = std::numeric_limits<double>::infinity();
104 101
105 // Set dischargingTime if it's available and valid, i.e. when on battery 102 // Set dischargingTime if it's available and valid, i.e. when on battery
106 // power. Otherwise leave the default value, which is +infinity. 103 // power. Otherwise leave the default value, which is +infinity.
107 if (on_battery_power) { 104 if (on_battery_power) {
108 SInt64 discharging_time = 105 SInt64 discharging_time =
109 GetValueAsSInt64(description, CFSTR(kIOPSTimeToEmptyKey), -1); 106 GetValueAsSInt64(description, CFSTR(kIOPSTimeToEmptyKey), -1);
110 if (discharging_time != -1) { 107 if (discharging_time != -1) {
111 status.dischargingTime = 108 status->discharging_time =
112 base::TimeDelta::FromMinutes(discharging_time).InSeconds(); 109 base::TimeDelta::FromMinutes(discharging_time).InSeconds();
113 } 110 }
114 } 111 }
115 } 112 }
116 } 113 }
117 114
118 std::vector<blink::WebBatteryStatus> GetInternalBatteriesStates() { 115 std::vector<BatteryStatus> GetInternalBatteriesStates() {
119 std::vector<blink::WebBatteryStatus> internal_sources; 116 std::vector<BatteryStatus> internal_sources;
120 117
121 base::ScopedCFTypeRef<CFTypeRef> info(IOPSCopyPowerSourcesInfo()); 118 base::ScopedCFTypeRef<CFTypeRef> info(IOPSCopyPowerSourcesInfo());
122 base::ScopedCFTypeRef<CFArrayRef> power_sources_list( 119 base::ScopedCFTypeRef<CFArrayRef> power_sources_list(
123 IOPSCopyPowerSourcesList(info)); 120 IOPSCopyPowerSourcesList(info));
124 CFIndex count = CFArrayGetCount(power_sources_list); 121 CFIndex count = CFArrayGetCount(power_sources_list);
125 122
126 for (CFIndex i = 0; i < count; ++i) { 123 for (CFIndex i = 0; i < count; ++i) {
127 CFDictionaryRef description = IOPSGetPowerSourceDescription(info, 124 CFDictionaryRef description = IOPSGetPowerSourceDescription(info,
128 CFArrayGetValueAtIndex(power_sources_list, i)); 125 CFArrayGetValueAtIndex(power_sources_list, i));
129 126
130 if (!description) 127 if (!description)
131 continue; 128 continue;
132 129
133 CFStringRef transport_type = 130 CFStringRef transport_type =
134 base::mac::GetValueFromDictionary<CFStringRef>(description, 131 base::mac::GetValueFromDictionary<CFStringRef>(description,
135 CFSTR(kIOPSTransportTypeKey)); 132 CFSTR(kIOPSTransportTypeKey));
136 133
137 bool internal_source = 134 bool internal_source =
138 CFStringsAreEqual(transport_type, CFSTR(kIOPSInternalType)); 135 CFStringsAreEqual(transport_type, CFSTR(kIOPSInternalType));
139 bool source_present = 136 bool source_present =
140 GetValueAsBoolean(description, CFSTR(kIOPSIsPresentKey), false); 137 GetValueAsBoolean(description, CFSTR(kIOPSIsPresentKey), false);
141 138
142 if (internal_source && source_present) { 139 if (internal_source && source_present) {
143 blink::WebBatteryStatus status; 140 BatteryStatus status;
144 FetchBatteryStatus(description, status); 141 FetchBatteryStatus(description, &status);
145 internal_sources.push_back(status); 142 internal_sources.push_back(status);
146 } 143 }
147 } 144 }
148 145
149 return internal_sources; 146 return internal_sources;
150 } 147 }
151 148
152 void OnBatteryStatusChanged(const BatteryCallback& callback) { 149 void OnBatteryStatusChanged(const BatteryCallback& callback) {
153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
154 151
155 std::vector<blink::WebBatteryStatus> batteries(GetInternalBatteriesStates()); 152 std::vector<BatteryStatus> batteries(GetInternalBatteriesStates());
156 153
157 if (batteries.empty()) { 154 if (batteries.empty()) {
158 callback.Run(blink::WebBatteryStatus()); 155 callback.Run(BatteryStatus());
159 return; 156 return;
160 } 157 }
161 158
162 // TODO(timvolodine): implement the case when there are multiple internal 159 // TODO(timvolodine): implement the case when there are multiple internal
163 // sources, e.g. when multiple batteries are present. Currently this will 160 // sources, e.g. when multiple batteries are present. Currently this will
164 // fail a DCHECK. 161 // fail a DCHECK.
165 DCHECK(batteries.size() == 1); 162 DCHECK(batteries.size() == 1);
166 callback.Run(batteries.front()); 163 callback.Run(batteries.front());
167 } 164 }
168 165
169 class BatteryStatusObserver 166 class BatteryStatusObserver
170 : public base::RefCountedThreadSafe<BatteryStatusObserver> { 167 : public base::RefCountedThreadSafe<BatteryStatusObserver> {
171 public: 168 public:
172 explicit BatteryStatusObserver(const BatteryCallback& callback) 169 explicit BatteryStatusObserver(const BatteryCallback& callback)
173 : callback_(callback) {} 170 : callback_(callback) {}
174 171
175 void Start() { 172 void Start() {
176 // Need to start on a thread with UI-type message loop for
177 // |notifier_run_loop_| to receive callbacks.
178 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
179 StartOnUI();
180 } else {
181 BrowserThread::PostTask(
182 BrowserThread::UI,
183 FROM_HERE,
184 base::Bind(&BatteryStatusObserver::StartOnUI, this));
185 }
186 }
187
188 void Stop() {
189 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
190 StopOnUI();
191 } else {
192 BrowserThread::PostTask(
193 BrowserThread::UI,
194 FROM_HERE,
195 base::Bind(&BatteryStatusObserver::StopOnUI, this));
196 }
197 }
198
199 private:
200 friend class base::RefCountedThreadSafe<BatteryStatusObserver>;
201 virtual ~BatteryStatusObserver() { DCHECK(!notifier_run_loop_source_); }
202
203 void StartOnUI() {
204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
205
206 if (notifier_run_loop_source_) 173 if (notifier_run_loop_source_)
207 return; 174 return;
208 175
209 notifier_run_loop_source_.reset( 176 notifier_run_loop_source_.reset(
210 IOPSNotificationCreateRunLoopSource(OnBatteryStatusChangedUI, 177 IOPSNotificationCreateRunLoopSource(CallOnBatteryStatusChanged,
211 static_cast<void*>(&callback_))); 178 static_cast<void*>(&callback_)));
212 if (!notifier_run_loop_source_) { 179 if (!notifier_run_loop_source_) {
213 LOG(ERROR) << "Failed to create battery status notification run loop"; 180 LOG(ERROR) << "Failed to create battery status notification run loop";
214 // Make sure to execute to callback with the default values. 181 // Make sure to execute to callback with the default values.
215 callback_.Run(blink::WebBatteryStatus()); 182 callback_.Run(BatteryStatus());
216 return; 183 return;
217 } 184 }
218 185
219 OnBatteryStatusChangedUI(static_cast<void*>(&callback_)); 186 CallOnBatteryStatusChanged(static_cast<void*>(&callback_));
220 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifier_run_loop_source_, 187 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifier_run_loop_source_,
221 kCFRunLoopDefaultMode); 188 kCFRunLoopDefaultMode);
222 UpdateNumberBatteriesHistogram(GetInternalBatteriesStates().size()); 189 UpdateNumberBatteriesHistogram(GetInternalBatteriesStates().size());
223 } 190 }
224 191
225 void StopOnUI() { 192 void Stop() {
226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
227
228 if (!notifier_run_loop_source_) 193 if (!notifier_run_loop_source_)
229 return; 194 return;
230 195
231 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifier_run_loop_source_, 196 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifier_run_loop_source_,
232 kCFRunLoopDefaultMode); 197 kCFRunLoopDefaultMode);
233 notifier_run_loop_source_.reset(); 198 notifier_run_loop_source_.reset();
234 } 199 }
235 200
236 static void OnBatteryStatusChangedUI(void* callback) { 201 private:
237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 202 friend class base::RefCountedThreadSafe<BatteryStatusObserver>;
238 // Offload fetching of values and callback execution to the IO thread. 203 virtual ~BatteryStatusObserver() { DCHECK(!notifier_run_loop_source_); }
239 BrowserThread::PostTask( 204
240 BrowserThread::IO, 205 static void CallOnBatteryStatusChanged(void* callback) {
241 FROM_HERE, 206 OnBatteryStatusChanged(*static_cast<BatteryCallback*>(callback));
242 base::Bind(&OnBatteryStatusChanged,
243 *static_cast<BatteryCallback*>(callback)));
244 } 207 }
245 208
246 BatteryCallback callback_; 209 BatteryCallback callback_;
247 base::ScopedCFTypeRef<CFRunLoopSourceRef> notifier_run_loop_source_; 210 base::ScopedCFTypeRef<CFRunLoopSourceRef> notifier_run_loop_source_;
248 211
249 DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver); 212 DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver);
250 }; 213 };
251 214
252 class BatteryStatusManagerMac : public BatteryStatusManager { 215 class BatteryStatusManagerMac : public BatteryStatusManager {
253 public: 216 public:
254 explicit BatteryStatusManagerMac(const BatteryCallback& callback) 217 explicit BatteryStatusManagerMac(const BatteryCallback& callback)
255 : notifier_(new BatteryStatusObserver(callback)) {} 218 : notifier_(new BatteryStatusObserver(callback)) {}
256 219
257 virtual ~BatteryStatusManagerMac() { 220 virtual ~BatteryStatusManagerMac() {
258 notifier_->Stop(); 221 notifier_->Stop();
259 } 222 }
260 223
261 // BatteryStatusManager: 224 // BatteryStatusManager:
262 virtual bool StartListeningBatteryChange() OVERRIDE { 225 virtual bool StartListeningBatteryChange() OVERRIDE {
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
264 notifier_->Start(); 226 notifier_->Start();
265 return true; 227 return true;
266 } 228 }
267 229
268 virtual void StopListeningBatteryChange() OVERRIDE { 230 virtual void StopListeningBatteryChange() OVERRIDE {
269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
270 notifier_->Stop(); 231 notifier_->Stop();
271 } 232 }
272 233
273 private: 234 private:
274 scoped_refptr<BatteryStatusObserver> notifier_; 235 scoped_refptr<BatteryStatusObserver> notifier_;
275 236
276 DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerMac); 237 DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerMac);
277 }; 238 };
278 239
279 } // end namespace 240 } // end namespace
280 241
281 // static 242 // static
282 scoped_ptr<BatteryStatusManager> BatteryStatusManager::Create( 243 scoped_ptr<BatteryStatusManager> BatteryStatusManager::Create(
283 const BatteryStatusService::BatteryUpdateCallback& callback) { 244 const BatteryStatusService::BatteryUpdateCallback& callback) {
284 return scoped_ptr<BatteryStatusManager>( 245 return scoped_ptr<BatteryStatusManager>(
285 new BatteryStatusManagerMac(callback)); 246 new BatteryStatusManagerMac(callback));
286 } 247 }
287 248
288 } // namespace content 249 } // namespace device
OLDNEW
« no previous file with comments | « device/battery/battery_status_manager_linux_unittest.cc ('k') | device/battery/battery_status_manager_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698