From e341217fea844e1c45b7079146b9de7cb68e8c2a Mon Sep 17 00:00:00 2001 From: Benny Baumann Date: Thu, 29 Jul 2021 23:53:58 +0200 Subject: Properly handle multiple batteries on darwin This makes the behaviour consistent with other platforms where AC is marked as present if at least one power source is marked as AC_PRESENT. Fixes: #711 --- darwin/Platform.c | 80 ++++++++++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 45 deletions(-) (limited to 'darwin/Platform.c') diff --git a/darwin/Platform.c b/darwin/Platform.c index 3fcf314d..df7e133f 100644 --- a/darwin/Platform.c +++ b/darwin/Platform.c @@ -347,67 +347,57 @@ bool Platform_getNetworkIO(NetworkIOData* data) { } void Platform_getBattery(double* percent, ACPresence* isOnAC) { - CFTypeRef power_sources = IOPSCopyPowerSourcesInfo(); - *percent = NAN; *isOnAC = AC_ERROR; - if (NULL == power_sources) - return; + CFArrayRef list = NULL; - CFArrayRef list = IOPSCopyPowerSourcesList(power_sources); - CFDictionaryRef battery = NULL; - int len; - - if (NULL == list) { - CFRelease(power_sources); + CFTypeRef power_sources = IOPSCopyPowerSourcesInfo(); + if (!power_sources) + goto cleanup; - return; - } + list = IOPSCopyPowerSourcesList(power_sources); + if (!list) + goto cleanup; - len = CFArrayGetCount(list); + double cap_current = 0.0; + double cap_max = 0.0; /* Get the battery */ - for (int i = 0; i < len && battery == NULL; ++i) { - CFDictionaryRef candidate = IOPSGetPowerSourceDescription(power_sources, - CFArrayGetValueAtIndex(list, i)); /* GET rule */ - CFStringRef type; - - if (NULL != candidate) { - type = (CFStringRef) CFDictionaryGetValue(candidate, - CFSTR(kIOPSTransportTypeKey)); /* GET rule */ - - if (kCFCompareEqualTo == CFStringCompare(type, CFSTR(kIOPSInternalType), 0)) { - CFRetain(candidate); - battery = candidate; - } - } - } + for (int i = 0, len = CFArrayGetCount(list); i < len; ++i) { + CFDictionaryRef power_source = IOPSGetPowerSourceDescription(power_sources, CFArrayGetValueAtIndex(list, i)); /* GET rule */ - if (NULL != battery) { - /* Determine the AC state */ - CFStringRef power_state = CFDictionaryGetValue(battery, CFSTR(kIOPSPowerSourceStateKey)); + if (!power_source) + continue; - *isOnAC = (kCFCompareEqualTo == CFStringCompare(power_state, CFSTR(kIOPSACPowerValue), 0)) - ? AC_PRESENT - : AC_ABSENT; + CFStringRef power_type = CFDictionaryGetValue(power_source, CFSTR(kIOPSTransportTypeKey)); /* GET rule */ - /* Get the percentage remaining */ - double current; - double max; + if (kCFCompareEqualTo != CFStringCompare(power_type, CFSTR(kIOPSInternalType), 0)) + continue; - CFNumberGetValue(CFDictionaryGetValue(battery, CFSTR(kIOPSCurrentCapacityKey)), - kCFNumberDoubleType, ¤t); - CFNumberGetValue(CFDictionaryGetValue(battery, CFSTR(kIOPSMaxCapacityKey)), - kCFNumberDoubleType, &max); + /* Determine the AC state */ + CFStringRef power_state = CFDictionaryGetValue(power_source, CFSTR(kIOPSPowerSourceStateKey)); - *percent = (current * 100.0) / max; + if (*isOnAC != AC_PRESENT) + *isOnAC = (kCFCompareEqualTo == CFStringCompare(power_state, CFSTR(kIOPSACPowerValue), 0)) ? AC_PRESENT : AC_ABSENT; - CFRelease(battery); + /* Get the percentage remaining */ + double tmp; + CFNumberGetValue(CFDictionaryGetValue(power_source, CFSTR(kIOPSCurrentCapacityKey)), kCFNumberDoubleType, &tmp); + cap_current += tmp; + CFNumberGetValue(CFDictionaryGetValue(power_source, CFSTR(kIOPSMaxCapacityKey)), kCFNumberDoubleType, &tmp); + cap_max += tmp; } - CFRelease(list); - CFRelease(power_sources); + if (cap_max > 0.0) + *percent = 100.0 * cap_current / cap_max; + +cleanup: + if (list) + CFRelease(list); + + if (power_sources) + CFRelease(power_sources); } void Platform_gettime_monotonic(uint64_t* msec) { -- cgit v1.2.3