| 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; |
| 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 |