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

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

Issue 685703002: Reland "Replace Chrome IPC with Mojo IPC for querying BatteryStatus service" (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address Tim's comments. Created 6 years, 1 month 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/scoped_ptr.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> {
171 public: 165 public:
172 explicit BatteryStatusObserver(const BatteryCallback& callback) 166 explicit BatteryStatusObserver(const BatteryCallback& callback)
173 : callback_(callback) {} 167 : callback_(callback) {}
174 168
169 ~BatteryStatusObserver() { DCHECK(!notifier_run_loop_source_); }
170
175 void Start() { 171 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_) 172 if (notifier_run_loop_source_)
207 return; 173 return;
208 174
209 notifier_run_loop_source_.reset( 175 notifier_run_loop_source_.reset(
210 IOPSNotificationCreateRunLoopSource(OnBatteryStatusChangedUI, 176 IOPSNotificationCreateRunLoopSource(CallOnBatteryStatusChanged,
211 static_cast<void*>(&callback_))); 177 static_cast<void*>(&callback_)));
212 if (!notifier_run_loop_source_) { 178 if (!notifier_run_loop_source_) {
213 LOG(ERROR) << "Failed to create battery status notification run loop"; 179 LOG(ERROR) << "Failed to create battery status notification run loop";
214 // Make sure to execute to callback with the default values. 180 // Make sure to execute to callback with the default values.
215 callback_.Run(blink::WebBatteryStatus()); 181 callback_.Run(BatteryStatus());
216 return; 182 return;
217 } 183 }
218 184
219 OnBatteryStatusChangedUI(static_cast<void*>(&callback_)); 185 CallOnBatteryStatusChanged(static_cast<void*>(&callback_));
220 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifier_run_loop_source_, 186 CFRunLoopAddSource(CFRunLoopGetCurrent(), notifier_run_loop_source_,
221 kCFRunLoopDefaultMode); 187 kCFRunLoopDefaultMode);
222 UpdateNumberBatteriesHistogram(GetInternalBatteriesStates().size()); 188 UpdateNumberBatteriesHistogram(GetInternalBatteriesStates().size());
223 } 189 }
224 190
225 void StopOnUI() { 191 void Stop() {
226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
227
228 if (!notifier_run_loop_source_) 192 if (!notifier_run_loop_source_)
229 return; 193 return;
230 194
231 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifier_run_loop_source_, 195 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), notifier_run_loop_source_,
232 kCFRunLoopDefaultMode); 196 kCFRunLoopDefaultMode);
233 notifier_run_loop_source_.reset(); 197 notifier_run_loop_source_.reset();
234 } 198 }
235 199
236 static void OnBatteryStatusChangedUI(void* callback) { 200 private:
237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 201 static void CallOnBatteryStatusChanged(void* callback) {
238 // Offload fetching of values and callback execution to the IO thread. 202 OnBatteryStatusChanged(*static_cast<BatteryCallback*>(callback));
239 BrowserThread::PostTask(
240 BrowserThread::IO,
241 FROM_HERE,
242 base::Bind(&OnBatteryStatusChanged,
243 *static_cast<BatteryCallback*>(callback)));
244 } 203 }
245 204
246 BatteryCallback callback_; 205 BatteryCallback callback_;
247 base::ScopedCFTypeRef<CFRunLoopSourceRef> notifier_run_loop_source_; 206 base::ScopedCFTypeRef<CFRunLoopSourceRef> notifier_run_loop_source_;
248 207
249 DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver); 208 DISALLOW_COPY_AND_ASSIGN(BatteryStatusObserver);
250 }; 209 };
251 210
252 class BatteryStatusManagerMac : public BatteryStatusManager { 211 class BatteryStatusManagerMac : public BatteryStatusManager {
253 public: 212 public:
254 explicit BatteryStatusManagerMac(const BatteryCallback& callback) 213 explicit BatteryStatusManagerMac(const BatteryCallback& callback)
255 : notifier_(new BatteryStatusObserver(callback)) {} 214 : notifier_(new BatteryStatusObserver(callback)) {}
256 215
257 ~BatteryStatusManagerMac() override { notifier_->Stop(); } 216 ~BatteryStatusManagerMac() override { notifier_->Stop(); }
258 217
259 // BatteryStatusManager: 218 // BatteryStatusManager:
260 bool StartListeningBatteryChange() override { 219 bool StartListeningBatteryChange() override {
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
262 notifier_->Start(); 220 notifier_->Start();
263 return true; 221 return true;
264 } 222 }
265 223
266 void StopListeningBatteryChange() override { 224 void StopListeningBatteryChange() override {
267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
268 notifier_->Stop(); 225 notifier_->Stop();
269 } 226 }
270 227
271 private: 228 private:
272 scoped_refptr<BatteryStatusObserver> notifier_; 229 scoped_ptr<BatteryStatusObserver> notifier_;
273 230
274 DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerMac); 231 DISALLOW_COPY_AND_ASSIGN(BatteryStatusManagerMac);
275 }; 232 };
276 233
277 } // end namespace 234 } // end namespace
278 235
279 // static 236 // static
280 scoped_ptr<BatteryStatusManager> BatteryStatusManager::Create( 237 scoped_ptr<BatteryStatusManager> BatteryStatusManager::Create(
281 const BatteryStatusService::BatteryUpdateCallback& callback) { 238 const BatteryStatusService::BatteryUpdateCallback& callback) {
282 return scoped_ptr<BatteryStatusManager>( 239 return scoped_ptr<BatteryStatusManager>(
283 new BatteryStatusManagerMac(callback)); 240 new BatteryStatusManagerMac(callback));
284 } 241 }
285 242
286 } // namespace content 243 } // 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