Index: base/power_monitor/power_monitor_device_source_mac.mm |
diff --git a/base/power_monitor/power_monitor_device_source_mac.mm b/base/power_monitor/power_monitor_device_source_mac.mm |
index 8c48117e22007f522e6d4433ff3e1ed621fb3f31..be2b8b947438dde50b7199a0b2551562721aa4cf 100644 |
--- a/base/power_monitor/power_monitor_device_source_mac.mm |
+++ b/base/power_monitor/power_monitor_device_source_mac.mm |
@@ -7,10 +7,14 @@ |
#include "base/power_monitor/power_monitor_device_source.h" |
+#include "base/mac/foundation_util.h" |
+#include "base/mac/scoped_cftyperef.h" |
#include "base/power_monitor/power_monitor.h" |
#include "base/power_monitor/power_monitor_source.h" |
#include <IOKit/IOMessage.h> |
+#include <IOKit/ps/IOPSKeys.h> |
+#include <IOKit/ps/IOPowerSources.h> |
#include <IOKit/pwr_mgt/IOPMLib.h> |
namespace base { |
@@ -19,11 +23,44 @@ void ProcessPowerEventHelper(PowerMonitorSource::PowerEvent event) { |
PowerMonitorSource::ProcessPowerEvent(event); |
} |
+bool PowerMonitorDeviceSource::IsOnBatteryPowerImpl() { |
+ base::ScopedCFTypeRef<CFTypeRef> info(IOPSCopyPowerSourcesInfo()); |
+ base::ScopedCFTypeRef<CFArrayRef> power_sources_list( |
+ IOPSCopyPowerSourcesList(info)); |
+ |
+ const CFIndex count = CFArrayGetCount(power_sources_list); |
+ for (CFIndex i = 0; i < count; ++i) { |
+ const CFDictionaryRef description = IOPSGetPowerSourceDescription( |
+ info, CFArrayGetValueAtIndex(power_sources_list, i)); |
+ if (!description) |
+ continue; |
+ |
+ CFStringRef current_state = base::mac::GetValueFromDictionary<CFStringRef>( |
+ description, CFSTR(kIOPSPowerSourceStateKey)); |
+ |
+ if (!current_state) |
+ continue; |
+ |
+ // We only report "on battery power" if no source is on AC power. |
+ if (CFStringCompare(current_state, CFSTR(kIOPSBatteryPowerValue), 0) != |
+ kCFCompareEqualTo) { |
+ return false; |
+ } |
+ } |
+ |
+ return true; |
+} |
+ |
namespace { |
io_connect_t g_system_power_io_port = 0; |
IONotificationPortRef g_notification_port_ref = 0; |
io_object_t g_notifier_object = 0; |
+CFRunLoopSourceRef g_battery_status_ref = 0; |
Robert Sesek
2016/09/26 22:21:19
... like these could be member variables instead o
|
+ |
+void BatteryEventCallback(void*) { |
+ ProcessPowerEventHelper(PowerMonitorSource::POWER_STATE_EVENT); |
+} |
void SystemPowerEventCallback(void*, |
io_service_t service, |
@@ -73,11 +110,16 @@ void PowerMonitorDeviceSource::PlatformInit() { |
if (g_system_power_io_port == 0) |
return; |
- // Add the notification port to the application runloop |
- CFRunLoopAddSource( |
- CFRunLoopGetCurrent(), |
- IONotificationPortGetRunLoopSource(g_notification_port_ref), |
- kCFRunLoopCommonModes); |
+ // Add the notification port and battery monitor to the application runloop |
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource( |
+ g_notification_port_ref), |
+ kCFRunLoopCommonModes); |
+ |
+ base::ScopedCFTypeRef<CFRunLoopSourceRef> battery_status_ref( |
+ IOPSNotificationCreateRunLoopSource(BatteryEventCallback, nullptr)); |
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), battery_status_ref, |
+ kCFRunLoopDefaultMode); |
+ g_battery_status_ref = battery_status_ref.release(); |
} |
void PowerMonitorDeviceSource::PlatformDestroy() { |
@@ -91,6 +133,12 @@ void PowerMonitorDeviceSource::PlatformDestroy() { |
IONotificationPortGetRunLoopSource(g_notification_port_ref), |
kCFRunLoopCommonModes); |
+ base::ScopedCFTypeRef<CFRunLoopSourceRef> battery_status_ref( |
+ g_battery_status_ref); |
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), g_battery_status_ref, |
+ kCFRunLoopDefaultMode); |
+ g_battery_status_ref = 0; |
+ |
// Deregister for system sleep notifications |
IODeregisterForSystemPower(&g_notifier_object); |