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

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

Issue 592153002: Replace Chrome IPC with Mojo IPC for querying BatteryStatus service (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: GN Android fixes. Created 6 years, 2 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
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 std::vector<BatteryStatus> batteries(GetInternalBatteriesStates());
154
155 std::vector<blink::WebBatteryStatus> batteries(GetInternalBatteriesStates());
156 151
157 if (batteries.empty()) { 152 if (batteries.empty()) {
158 callback.Run(blink::WebBatteryStatus()); 153 callback.Run(BatteryStatus());
159 return; 154 return;
160 } 155 }
161 156
162 // TODO(timvolodine): implement the case when there are multiple internal 157 // TODO(timvolodine): implement the case when there are multiple internal
163 // sources, e.g. when multiple batteries are present. Currently this will 158 // sources, e.g. when multiple batteries are present. Currently this will
164 // fail a DCHECK. 159 // fail a DCHECK.
165 DCHECK(batteries.size() == 1); 160 DCHECK(batteries.size() == 1);
166 callback.Run(batteries.front()); 161 callback.Run(batteries.front());
167 } 162 }
168 163
169 class BatteryStatusObserver 164 class BatteryStatusObserver
170 : public base::RefCountedThreadSafe<BatteryStatusObserver> { 165 : public base::RefCountedThreadSafe<BatteryStatusObserver> {
171 public: 166 public:
172 explicit BatteryStatusObserver(const BatteryCallback& callback) 167 explicit BatteryStatusObserver(const BatteryCallback& callback)
173 : callback_(callback) {} 168 : callback_(callback) {}
174 169
175 void Start() { 170 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_) 171 if (notifier_run_loop_source_)
207 return; 172 return;
208 173
209 notifier_run_loop_source_.reset( 174 notifier_run_loop_source_.reset(
210 IOPSNotificationCreateRunLoopSource(OnBatteryStatusChangedUI, 175 IOPSNotificationCreateRunLoopSource(CallOnBatteryStatusChanged,
211 static_cast<void*>(&callback_))); 176 static_cast<void*>(&callback_)));
212 if (!notifier_run_loop_source_) { 177 if (!notifier_run_loop_source_) {
213 LOG(ERROR) << "Failed to create battery status notification run loop"; 178 LOG(ERROR) << "Failed to create battery status notification run loop";
214 // Make sure to execute to callback with the default values. 179 // Make sure to execute to callback with the default values.
215 callback_.Run(blink::WebBatteryStatus()); 180 callback_.Run(BatteryStatus());
216 return; 181 return;
217 } 182 }
218 183
219 OnBatteryStatusChangedUI(static_cast<void*>(&callback_)); 184 CallOnBatteryStatusChanged(static_cast<void*>(&callback_));
220 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifier_run_loop_source_, 185 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifier_run_loop_source_,
221 kCFRunLoopDefaultMode); 186 kCFRunLoopDefaultMode);
222 UpdateNumberBatteriesHistogram(GetInternalBatteriesStates().size()); 187 UpdateNumberBatteriesHistogram(GetInternalBatteriesStates().size());
223 } 188 }
224 189
225 void StopOnUI() { 190 void Stop() {
226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
227
228 if (!notifier_run_loop_source_) 191 if (!notifier_run_loop_source_)
229 return; 192 return;
230 193
231 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifier_run_loop_source_, 194 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifier_run_loop_source_,
232 kCFRunLoopDefaultMode); 195 kCFRunLoopDefaultMode);
233 notifier_run_loop_source_.reset(); 196 notifier_run_loop_source_.reset();
234 } 197 }
235 198
236 static void OnBatteryStatusChangedUI(void* callback) { 199 private:
237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 200 friend class base::RefCountedThreadSafe<BatteryStatusObserver>;
238 // Offload fetching of values and callback execution to the IO thread. 201 virtual ~BatteryStatusObserver() { DCHECK(!notifier_run_loop_source_); }
239 BrowserThread::PostTask( 202
240 BrowserThread::IO, 203 static void CallOnBatteryStatusChanged(void* callback) {
241 FROM_HERE, 204 OnBatteryStatusChanged(*static_cast<BatteryCallback*>(callback));
242 base::Bind(&OnBatteryStatusChanged,
243 *static_cast<BatteryCallback*>(callback)));
244 } 205 }
245 206
246 BatteryCallback callback_; 207 BatteryCallback callback_;
247 base::ScopedCFTypeRef<CFRunLoopSourceRef> notifier_run_loop_source_; 208 base::ScopedCFTypeRef<CFRunLoopSourceRef> notifier_run_loop_source_;
248 209
249 DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver); 210 DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver);
250 }; 211 };
251 212
252 class BatteryStatusManagerMac : public BatteryStatusManager { 213 class BatteryStatusManagerMac : public BatteryStatusManager {
253 public: 214 public:
254 explicit BatteryStatusManagerMac(const BatteryCallback& callback) 215 explicit BatteryStatusManagerMac(const BatteryCallback& callback)
255 : notifier_(new BatteryStatusObserver(callback)) {} 216 : notifier_(new BatteryStatusObserver(callback)) {}
256 217
257 virtual ~BatteryStatusManagerMac() { 218 virtual ~BatteryStatusManagerMac() {
258 notifier_->Stop(); 219 notifier_->Stop();
259 } 220 }
260 221
261 // BatteryStatusManager: 222 // BatteryStatusManager:
262 virtual bool StartListeningBatteryChange() OVERRIDE { 223 virtual bool StartListeningBatteryChange() OVERRIDE {
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
264 notifier_->Start(); 224 notifier_->Start();
265 return true; 225 return true;
266 } 226 }
267 227
268 virtual void StopListeningBatteryChange() OVERRIDE { 228 virtual void StopListeningBatteryChange() OVERRIDE {
269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
270 notifier_->Stop(); 229 notifier_->Stop();
271 } 230 }
272 231
273 private: 232 private:
274 scoped_refptr<BatteryStatusObserver> notifier_; 233 scoped_refptr<BatteryStatusObserver> notifier_;
timvolodine 2014/09/25 23:08:33 now that the whole thing runs on UI thread we can
ppi 2014/09/29 16:43:26 Done.
275 234
276 DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerMac); 235 DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerMac);
277 }; 236 };
278 237
279 } // end namespace 238 } // end namespace
280 239
281 // static 240 // static
282 scoped_ptr<BatteryStatusManager> BatteryStatusManager::Create( 241 scoped_ptr<BatteryStatusManager> BatteryStatusManager::Create(
283 const BatteryStatusService::BatteryUpdateCallback& callback) { 242 const BatteryStatusService::BatteryUpdateCallback& callback) {
284 return scoped_ptr<BatteryStatusManager>( 243 return scoped_ptr<BatteryStatusManager>(
285 new BatteryStatusManagerMac(callback)); 244 new BatteryStatusManagerMac(callback));
286 } 245 }
287 246
288 } // namespace content 247 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698