OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 // Implementation based on sample code from | 5 // Implementation based on sample code from |
6 // http://developer.apple.com/library/mac/#qa/qa1340/_index.html. | 6 // http://developer.apple.com/library/mac/#qa/qa1340/_index.html. |
7 | 7 |
8 #include "base/power_monitor/power_monitor_device_source.h" | 8 #include "base/power_monitor/power_monitor_device_source.h" |
9 | 9 |
10 #include "base/mac/foundation_util.h" | |
11 #include "base/mac/scoped_cftyperef.h" | |
10 #include "base/power_monitor/power_monitor.h" | 12 #include "base/power_monitor/power_monitor.h" |
11 #include "base/power_monitor/power_monitor_source.h" | 13 #include "base/power_monitor/power_monitor_source.h" |
12 | 14 |
13 #include <IOKit/IOMessage.h> | 15 #include <IOKit/IOMessage.h> |
16 #include <IOKit/ps/IOPSKeys.h> | |
17 #include <IOKit/ps/IOPowerSources.h> | |
14 #include <IOKit/pwr_mgt/IOPMLib.h> | 18 #include <IOKit/pwr_mgt/IOPMLib.h> |
15 | 19 |
16 namespace base { | 20 namespace base { |
17 | 21 |
18 void ProcessPowerEventHelper(PowerMonitorSource::PowerEvent event) { | 22 void ProcessPowerEventHelper(PowerMonitorSource::PowerEvent event) { |
19 PowerMonitorSource::ProcessPowerEvent(event); | 23 PowerMonitorSource::ProcessPowerEvent(event); |
20 } | 24 } |
21 | 25 |
26 bool PowerMonitorDeviceSource::IsOnBatteryPowerImpl() { | |
27 base::ScopedCFTypeRef<CFTypeRef> info(IOPSCopyPowerSourcesInfo()); | |
28 base::ScopedCFTypeRef<CFArrayRef> power_sources_list( | |
29 IOPSCopyPowerSourcesList(info)); | |
30 | |
31 const CFIndex count = CFArrayGetCount(power_sources_list); | |
32 for (CFIndex i = 0; i < count; ++i) { | |
33 const CFDictionaryRef description = IOPSGetPowerSourceDescription( | |
34 info, CFArrayGetValueAtIndex(power_sources_list, i)); | |
35 if (!description) | |
36 continue; | |
37 | |
38 CFStringRef current_state = base::mac::GetValueFromDictionary<CFStringRef>( | |
39 description, CFSTR(kIOPSPowerSourceStateKey)); | |
40 | |
41 if (!current_state) | |
42 continue; | |
43 | |
44 // We only report "on battery power" if no source is on AC power. | |
45 if (CFStringCompare(current_state, CFSTR(kIOPSBatteryPowerValue), 0) != | |
46 kCFCompareEqualTo) { | |
47 return false; | |
48 } | |
49 } | |
50 | |
51 return true; | |
52 } | |
53 | |
22 namespace { | 54 namespace { |
23 | 55 |
24 io_connect_t g_system_power_io_port = 0; | 56 io_connect_t g_system_power_io_port = 0; |
25 IONotificationPortRef g_notification_port_ref = 0; | 57 IONotificationPortRef g_notification_port_ref = 0; |
26 io_object_t g_notifier_object = 0; | 58 io_object_t g_notifier_object = 0; |
59 CFRunLoopSourceRef g_battery_status_ref = 0; | |
Robert Sesek
2016/09/26 22:21:19
... like these could be member variables instead o
| |
60 | |
61 void BatteryEventCallback(void*) { | |
62 ProcessPowerEventHelper(PowerMonitorSource::POWER_STATE_EVENT); | |
63 } | |
27 | 64 |
28 void SystemPowerEventCallback(void*, | 65 void SystemPowerEventCallback(void*, |
29 io_service_t service, | 66 io_service_t service, |
30 natural_t message_type, | 67 natural_t message_type, |
31 void* message_argument) { | 68 void* message_argument) { |
32 switch (message_type) { | 69 switch (message_type) { |
33 // If this message is not handled the system may delay sleep for 30 seconds. | 70 // If this message is not handled the system may delay sleep for 30 seconds. |
34 case kIOMessageCanSystemSleep: | 71 case kIOMessageCanSystemSleep: |
35 IOAllowPowerChange(g_system_power_io_port, | 72 IOAllowPowerChange(g_system_power_io_port, |
36 reinterpret_cast<intptr_t>(message_argument)); | 73 reinterpret_cast<intptr_t>(message_argument)); |
(...skipping 29 matching lines...) Expand all Loading... | |
66 DCHECK_NE(g_system_power_io_port, 0u); | 103 DCHECK_NE(g_system_power_io_port, 0u); |
67 } | 104 } |
68 | 105 |
69 void PowerMonitorDeviceSource::PlatformInit() { | 106 void PowerMonitorDeviceSource::PlatformInit() { |
70 // Need to call AllocateSystemIOPorts() before creating a PowerMonitor | 107 // Need to call AllocateSystemIOPorts() before creating a PowerMonitor |
71 // object. | 108 // object. |
72 DCHECK_NE(g_system_power_io_port, 0u); | 109 DCHECK_NE(g_system_power_io_port, 0u); |
73 if (g_system_power_io_port == 0) | 110 if (g_system_power_io_port == 0) |
74 return; | 111 return; |
75 | 112 |
76 // Add the notification port to the application runloop | 113 // Add the notification port and battery monitor to the application runloop |
77 CFRunLoopAddSource( | 114 CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource( |
78 CFRunLoopGetCurrent(), | 115 g_notification_port_ref), |
79 IONotificationPortGetRunLoopSource(g_notification_port_ref), | 116 kCFRunLoopCommonModes); |
80 kCFRunLoopCommonModes); | 117 |
118 base::ScopedCFTypeRef<CFRunLoopSourceRef> battery_status_ref( | |
119 IOPSNotificationCreateRunLoopSource(BatteryEventCallback, nullptr)); | |
120 CFRunLoopAddSource(CFRunLoopGetCurrent(), battery_status_ref, | |
121 kCFRunLoopDefaultMode); | |
122 g_battery_status_ref = battery_status_ref.release(); | |
81 } | 123 } |
82 | 124 |
83 void PowerMonitorDeviceSource::PlatformDestroy() { | 125 void PowerMonitorDeviceSource::PlatformDestroy() { |
84 DCHECK_NE(g_system_power_io_port, 0u); | 126 DCHECK_NE(g_system_power_io_port, 0u); |
85 if (g_system_power_io_port == 0) | 127 if (g_system_power_io_port == 0) |
86 return; | 128 return; |
87 | 129 |
88 // Remove the sleep notification port from the application runloop | 130 // Remove the sleep notification port from the application runloop |
89 CFRunLoopRemoveSource( | 131 CFRunLoopRemoveSource( |
90 CFRunLoopGetCurrent(), | 132 CFRunLoopGetCurrent(), |
91 IONotificationPortGetRunLoopSource(g_notification_port_ref), | 133 IONotificationPortGetRunLoopSource(g_notification_port_ref), |
92 kCFRunLoopCommonModes); | 134 kCFRunLoopCommonModes); |
93 | 135 |
136 base::ScopedCFTypeRef<CFRunLoopSourceRef> battery_status_ref( | |
137 g_battery_status_ref); | |
138 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), g_battery_status_ref, | |
139 kCFRunLoopDefaultMode); | |
140 g_battery_status_ref = 0; | |
141 | |
94 // Deregister for system sleep notifications | 142 // Deregister for system sleep notifications |
95 IODeregisterForSystemPower(&g_notifier_object); | 143 IODeregisterForSystemPower(&g_notifier_object); |
96 | 144 |
97 // IORegisterForSystemPower implicitly opens the Root Power Domain IOService, | 145 // IORegisterForSystemPower implicitly opens the Root Power Domain IOService, |
98 // so we close it here. | 146 // so we close it here. |
99 IOServiceClose(g_system_power_io_port); | 147 IOServiceClose(g_system_power_io_port); |
100 | 148 |
101 g_system_power_io_port = 0; | 149 g_system_power_io_port = 0; |
102 | 150 |
103 // Destroy the notification port allocated by IORegisterForSystemPower. | 151 // Destroy the notification port allocated by IORegisterForSystemPower. |
104 IONotificationPortDestroy(g_notification_port_ref); | 152 IONotificationPortDestroy(g_notification_port_ref); |
105 } | 153 } |
106 | 154 |
107 } // namespace base | 155 } // namespace base |
OLD | NEW |