#include <sys/cdefs.h>
#include <TargetConditionals.h>
#include "IOSystemConfiguration.h"
#include <CoreFoundation/CoreFoundation.h>
#if !TARGET_OS_IPHONE
#include <IOKit/platform/IOPlatformSupportPrivate.h>
#endif
#include <IOKit/pwr_mgt/IOPM.h>
#include <IOKit/pwr_mgt/IOPMPrivate.h>
#include <IOKit/ps/IOPowerSources.h>
#include <IOKit/ps/IOPowerSourcesPrivate.h>
#include <IOKit/pwr_mgt/IOPMUPSPrivate.h>
#include <IOKit/IOCFSerialize.h>
#include <IOKit/IOHibernatePrivate.h>
#include <servers/bootstrap.h>
#include <bootstrap_priv.h>
#include <sys/syslog.h>
#include "IOPMLib.h"
#include "IOPMLibPrivate.h"
#include "powermanagement.h"
#include <asl.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOBSD.h>
#include <mach/mach.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <notify.h>
#include <os/log.h>
typedef struct {
const char *keyName;
uint32_t defaultValueAC;
uint32_t defaultValueBattery;
uint32_t defaultValueUPS;
} PMSettingDescriptorStruct;
PMSettingDescriptorStruct defaultSettings[] =
{
{kIOPMAutoPowerOffDelayKey, 28800, 0, 0},
{kIOPMAutoPowerOffEnabledKey, 0, 0, 0},
{kIOPMDarkWakeBackgroundTaskKey, 1, 0, 0},
{kIOPMDeepSleepEnabledKey, 0, 0, 0},
{kIOPMDeepSleepDelayKey, 0, 0, 0},
{kIOPMDiskSleepKey, 10, 10, 10},
{kIOPMDisplaySleepKey, 10, 2, 2},
{kIOPMDisplaySleepUsesDimKey, 1, 1, 1},
{kIOPMDynamicPowerStepKey, 1, 1, 0},
{kIOPMGPUSwitchKey, 2, 2, 2},
{kIOHibernateModeKey, 0, 0, 0},
{kIOPMMobileMotionModuleKey, 1, 1, 1},
{kIOPMPrioritizeNetworkReachabilityOverSleepKey, 0, 0, 0},
{kIOPMReduceBrightnessKey, 0, 1, 1},
{kIOPMReduceSpeedKey, 0, 0, 1},
{kIOPMRestartOnPowerLossKey, 0, 0, 0},
{kIOPMSleepOnPowerButtonKey, 1, 1, 1},
{kIOPMSystemSleepKey, 10, 10, 10},
{kIOPMTTYSPreventSleepKey, 1, 1, 1},
{kIOPMWakeOnACChangeKey, 0, 0, 0},
{kIOPMWakeOnClamshellKey, 1, 1, 1},
{kIOPMWakeOnLANKey, 1, 0, 0},
{kIOPMWakeOnRingKey, 1, 0, 0},
{kIOPMTCPKeepAlivePrefKey, 1, 1, 1},
{kIOPMProximityDarkWakeKey, 1, 0, 0},
};
static const int kPMSettingsCount = sizeof(defaultSettings)/sizeof(PMSettingDescriptorStruct);
static bool overridesSet = false;
#define kIOHibernateDefaultFile "/var/vm/sleepimage"
#define kIOPMSystemDefaultOverrideKey "SystemPowerProfileOverrideDict"
enum {
kIOPMSupportedOnAC = 1<<0,
kIOPMSupportedOnBatt = 1<<1,
kIOPMSupportedOnUPS = 1<<2
};
#define kPowerSourcesCount 3
static void updatePrefsDict(
CFMutableDictionaryRef prefs,
CFStringRef pwr_src,
CFStringRef key,
CFTypeRef value);
__private_extern__ io_registry_entry_t getPMRootDomainRef(void);
static CFStringRef supportedNameForPMName( CFStringRef pm_name );
static bool featureSupportsPowerSource(
CFTypeRef featureDetails,
CFStringRef power_source);
#define kOverWriteDuplicates true
#define kKeepOriginalValues false
static void mergeDictIntoMutable(
CFMutableDictionaryRef target,
CFDictionaryRef overrides,
bool overwrite);
static CFDictionaryRef getSystemProvidedPreferences(void);
static CFDictionaryRef copyDefaultPreferences(void);
static CFMutableDictionaryRef copyActivePreferences();
IOReturn _pm_connect(mach_port_t *newConnection);
IOReturn _pm_disconnect(mach_port_t connection);
typedef struct {
int dtoken;
} _PrefsChangeNotification;
IOPMNotificationHandle IOPMRegisterPrefsChangeNotification(dispatch_queue_t queue, void (^block)())
{
_PrefsChangeNotification *_prefschange = NULL;
uint32_t r = 0;
_prefschange = calloc(1, sizeof(_PrefsChangeNotification));
if (_prefschange)
{
r = notify_register_dispatch(kIOPMPrefsChangeNotify,
&_prefschange->dtoken,
queue,
block);
if (NOTIFY_STATUS_OK != r) {
free(_prefschange);
_prefschange = NULL;
}
}
return _prefschange;
}
void IOPMUnregisterPrefsChangeNotification(IOPMNotificationHandle handle)
{
_PrefsChangeNotification *_prefschange = (_PrefsChangeNotification *)handle;
if (_prefschange)
{
if (_prefschange->dtoken) {
notify_cancel(_prefschange->dtoken);
}
bzero(_prefschange, sizeof(*_prefschange));
free(_prefschange);
}
}
CFStringRef getGenericPrefsPath( )
{
return CFSTR(kIOPMCFPrefsPath);
}
CFStringRef getHostPrefsPath()
{
uuid_t uuid;
static CFStringRef uuidStr = NULL;
struct timespec ts = {1, 0};
int rc;
char cstr[100];
if (isA_CFString(uuidStr)) {
return uuidStr;
}
rc = gethostuuid(uuid, &ts);
if (rc == 0) {
snprintf(cstr, sizeof(cstr), "%s.%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
kIOPMCFPrefsPath,
uuid[0],uuid[1],uuid[2],uuid[3],uuid[4],
uuid[5],uuid[6],uuid[7],uuid[8],uuid[9],
uuid[10],uuid[11],uuid[12],uuid[13],uuid[14],uuid[15]);
uuidStr = CFStringCreateWithCString(kCFAllocatorDefault, cstr, kCFStringEncodingMacRoman);
}
else {
os_log(OS_LOG_DEFAULT, "Failed to get UUID. rc=%d\n", rc);
}
return uuidStr;
}
bool isA_GenericPref(CFStringRef key)
{
CFStringRef genericSettings[] = {
CFSTR(kIOPMDarkWakeBackgroundTaskKey),
CFSTR(kIOPMDiskSleepKey),
CFSTR(kIOPMDisplaySleepKey),
CFSTR(kIOPMDisplaySleepUsesDimKey),
CFSTR(kIOPMGPUSwitchKey),
CFSTR(kIOPMReduceBrightnessKey),
CFSTR(kIOPMRestartOnPowerLossKey),
CFSTR(kIOPMSystemSleepKey),
CFSTR(kIOPMWakeOnLANKey)
};
static CFSetRef genericSet = NULL;
if (genericSet == NULL) {
genericSet = CFSetCreate(0, (const void **)genericSettings,
sizeof(genericSettings)/sizeof(genericSettings[0]), &kCFTypeSetCallBacks);
if (genericSet == NULL) {
return NULL;
}
}
if (CFSetContainsValue(genericSet, key)) {
return true;
}
else {
return false;
}
}
CFMutableDictionaryRef copyPreferencesForSrc(CFStringRef power_source)
{
CFStringRef hostPrefsPath = getHostPrefsPath();
CFStringRef genericPrefsPath = getGenericPrefsPath();
CFDictionaryRef genericSettings = NULL;
CFDictionaryRef hostSettings = NULL;
CFMutableDictionaryRef settings = NULL;
genericSettings = IOPMCopyFromPrefs(genericPrefsPath, power_source);
if (isA_CFDictionary(genericSettings)) {
settings = CFDictionaryCreateMutableCopy(0, 0, genericSettings);
}
hostSettings = IOPMCopyFromPrefs(hostPrefsPath, power_source);
if (isA_CFDictionary(hostSettings)) {
if (settings) {
mergeDictIntoMutable(settings, hostSettings, kKeepOriginalValues);
}
else {
settings = CFDictionaryCreateMutableCopy(0, 0, hostSettings);
}
}
if (genericSettings) {
CFRelease(genericSettings);
}
if (hostSettings) {
CFRelease(hostSettings);
}
return settings;
}
bool setPreferencesForSrc(CFStringRef pwrSrc, CFDictionaryRef prefs, bool synchronize)
{
CFIndex count;
const CFStringRef *keys = NULL;
const CFTypeRef *objs = NULL;
bool ret = false;
CFStringRef hostPrefsPath = getHostPrefsPath();
CFStringRef genericPrefsPath = getGenericPrefsPath();
CFMutableDictionaryRef genericSettings = NULL;
CFMutableDictionaryRef hostSettings = NULL;
if (prefs == NULL) {
goto exit;
}
count = CFDictionaryGetCount(prefs);
if(0 == count) {
goto exit;
}
keys = (CFStringRef *)malloc(sizeof(CFStringRef) * count);
objs = (CFTypeRef *)malloc(sizeof(CFTypeRef) * count);
if(!keys || !objs) {
goto exit;
}
CFDictionaryGetKeysAndValues(prefs, (const void **)keys, (const void **)objs);
for(int i=0; i<count; i++) {
if (isA_GenericPref(keys[i])) {
if (genericSettings == NULL) {
CFDictionaryRef tmp = IOPMCopyFromPrefs(genericPrefsPath, pwrSrc);
if (tmp) {
genericSettings = CFDictionaryCreateMutableCopy(NULL, 0, tmp);
CFRelease(tmp);
}
else {
genericSettings = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
}
if (genericSettings) {
CFDictionarySetValue(genericSettings, keys[i], objs[i]);
}
}
else {
if (hostSettings == NULL) {
CFDictionaryRef tmp = IOPMCopyFromPrefs(hostPrefsPath, pwrSrc);
if (tmp) {
hostSettings = CFDictionaryCreateMutableCopy(NULL, 0, tmp);
CFRelease(tmp);
}
else {
hostSettings = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
}
if (hostSettings) {
CFDictionarySetValue(hostSettings, keys[i], objs[i]);
}
}
}
exit:
if (genericPrefsPath) {
if (genericSettings) {
CFPreferencesSetValue(pwrSrc, genericSettings, genericPrefsPath,
kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
}
else if (prefs == NULL) {
CFPreferencesSetValue(pwrSrc, NULL, genericPrefsPath,
kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
}
if (synchronize) {
ret = CFPreferencesSynchronize(genericPrefsPath,
kCFPreferencesAnyUser,
kCFPreferencesCurrentHost);
}
}
if (hostPrefsPath) {
if (hostSettings) {
CFPreferencesSetValue(pwrSrc, hostSettings, hostPrefsPath,
kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
}
else if (prefs == NULL) {
CFPreferencesSetValue(pwrSrc, NULL, hostPrefsPath,
kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
}
if (synchronize) {
ret &= CFPreferencesSynchronize(hostPrefsPath,
kCFPreferencesAnyUser,
kCFPreferencesCurrentHost);
}
}
if (keys) {
free((void *)keys);
}
if (objs) {
free((void *)objs);
}
if (genericSettings) {
CFRelease(genericSettings);
}
if (hostSettings) {
CFRelease(hostSettings);
}
return ret;
}
CFMutableDictionaryRef IOPMCopyPreferencesOnFile(void)
{
CFMutableDictionaryRef prefs = NULL;
unsigned int i;
CFStringRef pwrSrc[] = {CFSTR(kIOPMACPowerKey), CFSTR(kIOPMBatteryPowerKey), CFSTR(kIOPMUPSPowerKey)};
prefs = CFDictionaryCreateMutable(0, kPowerSourcesCount,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (!prefs) {
return NULL;
}
for (i = 0; i < sizeof(pwrSrc)/sizeof(pwrSrc[0]); i++) {
CFMutableDictionaryRef dict = copyPreferencesForSrc(pwrSrc[i]);
if (isA_CFDictionary(dict)) {
CFDictionarySetValue(prefs, pwrSrc[i], dict);
CFRelease(dict);
}
}
return prefs;
}
CFMutableDictionaryRef IOPMCopyPMPreferences(void)
{
return copyActivePreferences();
}
CFDictionaryRef IOPMCopyActivePMPreferences(void)
{
return IOPMCopyPMPreferences();
}
CFDictionaryRef IOPMCopyDefaultPreferences(void)
{
return getSystemProvidedPreferences();
}
#if !TARGET_OS_IPHONE
IOReturn IOPMCopyPMSetting(
CFStringRef key,
CFStringRef power_source,
CFTypeRef *outValue)
{
CFDictionaryRef ActiveSettings = NULL;
CFDictionaryRef perPS = NULL;
CFStringRef usePowerSource = power_source;
CFTypeRef psblob = NULL;
bool supported = false;
IOReturn ret;
if (!key || !outValue) {
ret = kIOReturnBadArgument;
goto exit;
}
*outValue = 0;
if (!usePowerSource) {
IOPSPowerSourceIndex activeps;
IOPSGetSupportedPowerSources(&activeps, NULL, NULL);
if (kIOPSProvidedByExternalBattery == activeps) {
usePowerSource = CFSTR(kIOPMUPSPowerKey);
} else if (kIOPSProvidedByBattery == activeps) {
usePowerSource = CFSTR(kIOPMBatteryPowerKey);
} else {
usePowerSource = CFSTR(kIOPMACPowerKey);
}
}
supported = IOPMFeatureIsAvailable(key, usePowerSource);
if (!supported) {
ret = kIOReturnUnsupported;
goto exit;
}
ActiveSettings = IOPMCopyPMPreferences();
if (ActiveSettings) {
perPS = (CFDictionaryRef)CFDictionaryGetValue(
ActiveSettings, usePowerSource);
if (perPS) {
*outValue = CFDictionaryGetValue(perPS, key);
}
}
if (*outValue) {
CFRetain(*outValue);
ret = kIOReturnSuccess;
} else {
ret = kIOReturnNotFound;
}
if (ActiveSettings) {
CFRelease(ActiveSettings);
}
exit:
if (psblob) {
CFRelease(psblob);
}
return ret;
}
#endif
bool comparePrefsToDefaults(CFDictionaryRef prefs, CFStringRef pwr_src)
{
CFIndex count;
bool matches = true;
CFTypeRef *defaultValue = NULL;
CFStringRef *keys = NULL;
CFTypeRef *prefsValues = NULL;
CFDictionaryRef defaults = NULL;
if (!prefs || ((count = CFDictionaryGetCount(prefs)) == 0)) {
return true;
}
defaults = getSystemProvidedPreferences();
CFDictionaryRef defaultsForSrc = CFDictionaryGetValue(defaults, pwr_src);
if (!defaultsForSrc || (CFDictionaryGetCount(defaultsForSrc) == 0)) {
matches = false;
goto exit;
}
keys = (CFStringRef *)malloc(sizeof(CFStringRef) * count);
prefsValues = (CFTypeRef *)malloc(sizeof(CFTypeRef) * count);
if(!keys || !prefsValues) {
matches = false;
goto exit;
}
CFDictionaryGetKeysAndValues(prefs, (const void **)keys, (const void **)prefsValues);
for (CFIndex idx = 0; idx < count; idx++) {
defaultValue = NULL;
if (!CFDictionaryGetValueIfPresent(defaultsForSrc, keys[idx], (const void **)&defaultValue)) {
matches = false;
break;
}
if (!CFEqual(defaultValue, prefsValues[idx])) {
matches = false;
break;
}
}
exit:
if (keys) {
free((void *)keys);
}
if (prefsValues) {
free((void *)prefsValues);
}
if (defaults) {
CFRelease(defaults);
}
return matches;
}
bool IOPMUsingDefaultPreferences(CFStringRef pwr_src)
{
bool ret = false;
if (isA_CFString(pwr_src)) {
CFDictionaryRef prefs = copyPreferencesForSrc(pwr_src);
ret = comparePrefsToDefaults(prefs, pwr_src);
if (prefs) CFRelease(prefs);
} else {
CFDictionaryRef acPrefs = copyPreferencesForSrc(CFSTR(kIOPMACPowerKey));
CFDictionaryRef battPrefs = copyPreferencesForSrc(CFSTR(kIOPMBatteryPowerKey));
CFDictionaryRef upsPrefs = copyPreferencesForSrc(CFSTR(kIOPMUPSPowerKey));
ret = true;
ret &= comparePrefsToDefaults(acPrefs, CFSTR(kIOPMACPowerKey));
if (ret) {
ret &= comparePrefsToDefaults(battPrefs, CFSTR(kIOPMBatteryPowerKey));
}
if (ret) {
ret &= comparePrefsToDefaults(upsPrefs, CFSTR(kIOPMUPSPowerKey));
}
if (acPrefs) CFRelease(acPrefs);
if (battPrefs) CFRelease(battPrefs);
if (upsPrefs) CFRelease(upsPrefs);
}
return ret;
}
IOReturn IOPMRevertPMPreferences(CFArrayRef keys_arr)
{
IOReturn ret = kIOReturnInternalError;
int count = 0;
CFStringRef setting = NULL;
CFMutableDictionaryRef prefs = IOPMCopyPreferencesOnFile();
if (!prefs) {
goto exit;
}
if (IOPMUsingDefaultPreferences(NULL)) {
ret = kIOReturnSuccess;
goto exit;
}
if (!keys_arr || (0 == (count = CFArrayGetCount(keys_arr)))) {
ret = IOPMSetPMPreferences(NULL);
goto exit;
}
for (int i = 0; i < count; i++) {
setting = CFArrayGetValueAtIndex(keys_arr, i);
if (isA_CFString(setting)) {
updatePrefsDict(prefs, CFSTR(kIOPMACPowerKey), setting, NULL);
updatePrefsDict(prefs, CFSTR(kIOPMBatteryPowerKey), setting, NULL);
updatePrefsDict(prefs, CFSTR(kIOPMUPSPowerKey), setting, NULL);
}
}
ret = IOPMSetPMPreferences(prefs);
exit:
if (prefs) CFRelease(prefs);
return ret;
}
static void updatePrefsDict(CFMutableDictionaryRef prefs,
CFStringRef pwr_src,
CFStringRef key,
CFTypeRef value)
{
CFMutableDictionaryRef dictRef = NULL;
CFDictionaryRef pwrDict = NULL;
pwrDict = CFDictionaryGetValue(prefs, pwr_src);
if (!pwrDict) {
return;
}
dictRef = CFDictionaryCreateMutableCopy(0, CFDictionaryGetCount(pwrDict), pwrDict);
if (dictRef) {
if (value) {
CFDictionarySetValue(dictRef, key, value);
} else {
CFDictionaryRemoveValue(dictRef, key);
}
CFDictionarySetValue(prefs, pwr_src, dictRef);
CFRelease(dictRef);
}
return;
}
IOReturn IOPMSetPMPreference(CFStringRef key,
CFTypeRef value,
CFStringRef pwr_src)
{
CFMutableDictionaryRef prefs = IOPMCopyPreferencesOnFile();
IOReturn ret = kIOReturnError;
if (!prefs) {
goto exit;
}
if (pwr_src) {
if (!CFDictionaryContainsKey(prefs, pwr_src)) {
ret = kIOReturnBadArgument;
goto exit;
}
}
if (key == NULL) {
if (pwr_src) {
CFDictionaryRemoveValue(prefs, pwr_src);
} else {
CFRelease(prefs);
prefs = NULL;
}
}
else {
if (pwr_src) {
updatePrefsDict(prefs, pwr_src, key, value);
} else {
updatePrefsDict(prefs, CFSTR(kIOPMACPowerKey), key, value);
updatePrefsDict(prefs, CFSTR(kIOPMBatteryPowerKey), key, value);
updatePrefsDict(prefs, CFSTR(kIOPMUPSPowerKey), key, value);
}
}
ret = IOPMSetPMPreferences(prefs);
exit:
if (prefs) CFRelease(prefs);
return ret;
}
IOReturn IOPMSetPMPreferences(CFDictionaryRef ESPrefs)
{
bool result = false;
CFDictionaryRef tmp = NULL;
if ((getuid() != 0) && (geteuid() != 0)) {
return kIOReturnNotPrivileged;
}
if (ESPrefs == NULL) {
setPreferencesForSrc(CFSTR(kIOPMACPowerKey), NULL, false);
setPreferencesForSrc(CFSTR(kIOPMBatteryPowerKey), NULL, false);
result = setPreferencesForSrc(CFSTR(kIOPMUPSPowerKey), NULL, true);
} else {
tmp = CFDictionaryGetValue(ESPrefs, CFSTR(kIOPMACPowerKey));
setPreferencesForSrc(CFSTR(kIOPMACPowerKey), tmp, false);
tmp = CFDictionaryGetValue(ESPrefs, CFSTR(kIOPMBatteryPowerKey));
setPreferencesForSrc(CFSTR(kIOPMBatteryPowerKey), tmp, false);
tmp = CFDictionaryGetValue(ESPrefs, CFSTR(kIOPMUPSPowerKey));
result = setPreferencesForSrc(CFSTR(kIOPMUPSPowerKey), tmp, true);
}
if (result) {
notify_post(kIOPMPrefsChangeNotify);
}
return (result ? kIOReturnSuccess : kIOReturnError);
}
IOReturn IOPMWriteToPrefs(CFStringRef key, CFTypeRef value,
bool synchronize, bool broadcast)
{
bool result = true;
CFStringRef prefsPath = NULL;
if ((getuid() != 0) && (geteuid() != 0)) {
return kIOReturnNotPrivileged;
}
if (isA_GenericPref(key)) {
prefsPath = getGenericPrefsPath();
}
else {
prefsPath = getHostPrefsPath();
}
CFPreferencesSetValue(key, value,
prefsPath,
kCFPreferencesAnyUser,
kCFPreferencesCurrentHost);
if (synchronize) {
result = CFPreferencesSynchronize(prefsPath,
kCFPreferencesAnyUser,
kCFPreferencesCurrentHost);
if (result && broadcast) {
notify_post(kIOPMPrefsChangeNotify);
}
}
return (result ? kIOReturnSuccess : kIOReturnError);
}
CFTypeRef IOPMCopyFromPrefs(CFStringRef prefsPath, CFStringRef key)
{
CFTypeRef value = NULL;
if (prefsPath == NULL) {
if (isA_GenericPref(key)) {
prefsPath = getGenericPrefsPath();
}
else {
prefsPath = getHostPrefsPath();
}
}
if (!isA_CFString(prefsPath)) {
return NULL;
}
value = CFPreferencesCopyValue(key,
prefsPath,
kCFPreferencesAnyUser,
kCFPreferencesCurrentHost);
return value;
}
bool IOPMFeatureIsAvailable(CFStringRef PMFeature, CFStringRef power_source)
{
CFDictionaryRef supportedFeatures = NULL;
io_registry_entry_t registry_entry = MACH_PORT_NULL;
int return_this_value = 0;
if(!(registry_entry = getPMRootDomainRef()))
return false;
supportedFeatures = IORegistryEntryCreateCFProperty(registry_entry, CFSTR("Supported Features"),
kCFAllocatorDefault, kNilOptions);
if (!supportedFeatures)
return false;
if( CFEqual(PMFeature, CFSTR(kIOPMDarkWakeBackgroundTaskKey)) )
{
#if TARGET_OS_IPHONE
goto exit;
#else
return_this_value = 0;
if (!power_source)
power_source = CFSTR(kIOPMACPowerKey);
CFTypeRef pnDetails = CFDictionaryGetValue( supportedFeatures,
CFSTR(kIOPMPowerNapSupportedKey));
if(featureSupportsPowerSource(pnDetails, power_source))
{
return_this_value = 1;
goto exit;
}
CFTypeRef btdetails = CFDictionaryGetValue( supportedFeatures,
CFSTR(kIOPMDarkWakeBackgroundTaskKey));
CFTypeRef ssdetails = CFDictionaryGetValue( supportedFeatures,
CFSTR(kIOPMSleepServicesKey));
if(featureSupportsPowerSource(btdetails, power_source) ||
featureSupportsPowerSource(ssdetails, power_source))
{
return_this_value = 1;
}
}
else if (CFEqual(PMFeature, CFSTR(kIOPMTCPKeepAlivePrefKey)))
{
CFTypeRef tcpka = kCFBooleanFalse;
IOPlatformCopyFeatureDefault(kIOPlatformTCPKeepAliveDuringSleep, &tcpka);
if (tcpka == kCFBooleanTrue)
return_this_value = 1;
else
return_this_value = 0;
#endif
}
else
{
return_this_value = IOPMFeatureIsAvailableWithSupportedTable(
PMFeature,
power_source,
supportedFeatures);
}
exit:
CFRelease(supportedFeatures);
return (return_this_value ? true:false);
}
bool IOPMFeatureIsAvailableWithSupportedTable(
CFStringRef PMFeature,
CFStringRef power_source,
CFDictionaryRef supportedFeatures)
{
CFStringRef supportedString = NULL;
CFTypeRef featureDetails = NULL;
bool ret = false;
if (!power_source)
power_source = CFSTR(kIOPMACPowerKey);
if (!supportedFeatures)
return false;
if (CFEqual(PMFeature, CFSTR(kIOPMDisplaySleepKey))
|| CFEqual(PMFeature, CFSTR(kIOPMSystemSleepKey))
|| CFEqual(PMFeature, CFSTR(kIOPMDiskSleepKey))
|| CFEqual(PMFeature, CFSTR(kIOPMTTYSPreventSleepKey))
|| CFEqual(PMFeature, kIOPMSleepDisabledKey)
|| CFEqual(PMFeature, CFSTR(kIOPMDestroyFVKeyOnStandbyKey)))
{
ret = true;
goto exit;
}
if (CFEqual(PMFeature, CFSTR(kIOPMRestartOnKernelPanicKey))) {
ret = false;
goto exit;
}
if(CFEqual(PMFeature, CFSTR(kIOPMSleepOnPowerButtonKey)))
{
#if TARGET_OS_IPHONE
ret = false;
#else
CFArrayRef tmp_array = NULL;
IOReturn r = IOPMCopyBatteryInfo(kIOMasterPortDefault, &tmp_array);
if((r == kIOReturnSuccess) && tmp_array)
{
CFRelease(tmp_array);
ret = false;
} else ret = true;
#endif
goto exit;
}
if ( CFEqual(PMFeature, CFSTR(kIOPMReduceBrightnessKey)) )
{
bool hasBatt = false;
bool hasUPS = false;
IOPSGetSupportedPowerSources(NULL, &hasBatt, &hasUPS);
if (( hasBatt || hasUPS )
&& supportedFeatures
&& CFDictionaryGetValue(supportedFeatures, CFSTR("DisplayDims"))
&& !CFEqual(power_source, CFSTR(kIOPMACPowerKey)) )
{
ret = true;
} else {
ret = false;
}
goto exit;
}
supportedString = supportedNameForPMName( PMFeature );
if(!supportedString) {
ret = false;
goto exit;
}
if (CFEqual(supportedString, CFSTR(kIOHibernateFeatureKey)) && !overridesSet) {
ret = false;
goto exit;
}
featureDetails = CFDictionaryGetValue(supportedFeatures, supportedString);
if(!featureDetails) {
ret = false;
goto exit;
}
if(featureSupportsPowerSource(featureDetails, power_source))
{
ret = true;
}
exit:
return ret;
}
__private_extern__ io_registry_entry_t getPMRootDomainRef(void)
{
static io_registry_entry_t cached_root_domain = MACH_PORT_NULL;
if( MACH_PORT_NULL == cached_root_domain ) {
cached_root_domain = IORegistryEntryFromPath( kIOMasterPortDefault,
kIOPowerPlane ":/IOPowerConnection/IOPMrootDomain");
}
return cached_root_domain;
}
static CFStringRef
supportedNameForPMName( CFStringRef pm_name )
{
#if TARGET_OS_IPHONE
if( CFEqual(pm_name, CFSTR(kIOPMReduceBrightnessKey))
|| CFEqual(pm_name, CFSTR(kIOPMDisplaySleepUsesDimKey)) )
#else
if(CFEqual(pm_name, CFSTR(kIOPMDisplaySleepUsesDimKey)))
#endif
{
return CFSTR("DisplayDims");
}
if(CFEqual(pm_name, CFSTR(kIOPMWakeOnLANKey))
|| CFEqual(pm_name, CFSTR(kIOPMPrioritizeNetworkReachabilityOverSleepKey)))
{
return CFSTR("WakeOnMagicPacket");
}
if(CFEqual(pm_name, CFSTR(kIOPMMobileMotionModuleKey)))
{
return CFSTR("MobileMotionModule");
}
if( CFEqual(pm_name, CFSTR(kIOHibernateModeKey))
|| CFEqual(pm_name, CFSTR(kIOHibernateFreeRatioKey))
|| CFEqual(pm_name, CFSTR(kIOHibernateFreeTimeKey))
|| CFEqual(pm_name, CFSTR(kIOHibernateFileKey))
|| CFEqual(pm_name, CFSTR(kIOHibernateFeatureKey)))
{
return CFSTR(kIOHibernateFeatureKey);
}
if (CFEqual(pm_name, CFSTR(kIOPMDeepSleepEnabledKey))
|| CFEqual(pm_name, CFSTR(kIOPMDeepSleepDelayKey))
|| CFEqual(pm_name, CFSTR(kIOPMDeepSleepDelayHighKey))
|| CFEqual(pm_name, CFSTR(kIOPMStandbyBatteryThresholdKey)))
{
return CFSTR("DeepSleep");
}
if (CFEqual(pm_name, CFSTR(kIOPMAutoPowerOffEnabledKey))
|| CFEqual(pm_name, CFSTR(kIOPMAutoPowerOffDelayKey)))
{
return CFSTR("AutoPowerOff");
}
if (CFEqual(pm_name, CFSTR(kIOPMProximityDarkWakeKey))) {
return CFSTR("ProximityWake");
}
return pm_name;
}
static bool
featureSupportsPowerSource(CFTypeRef featureDetails, CFStringRef power_source)
{
CFNumberRef featureNum = NULL;
CFNumberRef tempNum = NULL;
CFArrayRef featureArr = NULL;
uint32_t ps_support = 0;
uint32_t tmp;
unsigned int i;
if( (featureNum = isA_CFNumber(featureDetails)) )
{
CFNumberGetValue(featureNum, kCFNumberSInt32Type, &ps_support);
} else if( (featureArr = isA_CFArray(featureDetails)) )
{
unsigned int arrayCount = CFArrayGetCount(featureArr);
for(i = 0; i<arrayCount; i++)
{
tempNum = isA_CFNumber(CFArrayGetValueAtIndex(featureArr, i));
if(tempNum) {
CFNumberGetValue(tempNum, kCFNumberSInt32Type, &tmp);
ps_support |= tmp;
}
}
}
if(!power_source) {
return (ps_support ? true : false);
}
if(CFEqual(CFSTR(kIOPMACPowerKey), power_source) )
{
return (ps_support & kIOPMSupportedOnAC) ? true : false;
} else if(CFEqual(CFSTR(kIOPMBatteryPowerKey), power_source) )
{
return (ps_support & kIOPMSupportedOnBatt) ? true : false;
} else if(CFEqual(CFSTR(kIOPMUPSPowerKey), power_source) )
{
return (ps_support & kIOPMSupportedOnUPS) ? true : false;
} else {
return false;
}
}
static bool checkPowerSourceSupported(CFStringRef str)
{
bool hasBatt;
bool hasUPS;
if (CFEqual(str, CFSTR(kIOPMACPowerKey))) {
return true;
}
IOPSGetSupportedPowerSources(NULL, &hasBatt, &hasUPS);
if (CFEqual(str, CFSTR(kIOPMBatteryPowerKey))) {
return hasBatt;
}
if (CFEqual(str, CFSTR(kIOPMUPSPowerKey))) {
return hasUPS;
}
return false;
}
void IOPMRemoveIrrelevantProperties(CFMutableDictionaryRef energyPrefs)
{
int profile_count = 0;
int dict_count = 0;
CFStringRef *profile_keys = NULL;
CFDictionaryRef *profile_vals = NULL;
CFStringRef *dict_keys = NULL;
CFDictionaryRef *dict_vals = NULL;
CFMutableDictionaryRef this_profile = NULL;
CFDictionaryRef _supportedCached = NULL;
io_registry_entry_t _rootDomain = IO_OBJECT_NULL;
bool hasBatt = false;
bool hasUPS = false;
_rootDomain = getPMRootDomainRef();
if (IO_OBJECT_NULL != _rootDomain)
{
_supportedCached = IORegistryEntryCreateCFProperty(_rootDomain,
CFSTR("Supported Features"),
kCFAllocatorDefault, kNilOptions);
}
profile_count = CFDictionaryGetCount(energyPrefs);
profile_keys = (CFStringRef *)malloc(sizeof(CFStringRef) * profile_count);
profile_vals = (CFDictionaryRef *)malloc(sizeof(CFDictionaryRef) * profile_count);
if (!profile_keys || !profile_vals)
goto exit;
hasBatt = checkPowerSourceSupported(CFSTR(kIOPMBatteryPowerKey));
hasUPS = checkPowerSourceSupported(CFSTR(kIOPMUPSPowerKey));
CFDictionaryGetKeysAndValues(energyPrefs, (const void **)profile_keys,
(const void **)profile_vals);
while(--profile_count >= 0)
{
if ((CFEqual(profile_keys[profile_count], CFSTR(kIOPMBatteryPowerKey)) && !hasBatt) ||
(CFEqual(profile_keys[profile_count], CFSTR(kIOPMUPSPowerKey)) && !hasUPS))
{
CFDictionaryRemoveValue(energyPrefs, profile_keys[profile_count]);
} else {
this_profile = (CFMutableDictionaryRef)isA_CFDictionary(
CFDictionaryGetValue(energyPrefs, profile_keys[profile_count]));
if(!this_profile)
continue;
this_profile = CFDictionaryCreateMutableCopy(NULL, 0, this_profile);
if(!this_profile)
continue;
CFDictionarySetValue(energyPrefs, profile_keys[profile_count], this_profile);
CFRelease(this_profile);
dict_count = CFDictionaryGetCount(this_profile);
dict_keys = (CFStringRef *)malloc(sizeof(CFStringRef) * dict_count);
dict_vals = (CFDictionaryRef *)malloc(sizeof(CFDictionaryRef) * dict_count);
if (!dict_keys || !dict_vals)
continue;
CFDictionaryGetKeysAndValues(this_profile,
(const void **)dict_keys, (const void **)dict_vals);
while(--dict_count >= 0)
{
if( CFEqual((CFStringRef)dict_keys[dict_count], CFSTR(kIOPMDarkWakeBackgroundTaskKey)) )
{
#if !TARGET_OS_IPHONE
bool supportsNewPNKey = false;
if(IOPMFeatureIsAvailableWithSupportedTable( CFSTR(kIOPMPowerNapSupportedKey),
(CFStringRef)profile_keys[profile_count], _supportedCached)) {
supportsNewPNKey = true;
}
if ( ((!IOPMFeatureIsAvailableWithSupportedTable( CFSTR(kIOPMDarkWakeBackgroundTaskKey),
(CFStringRef)profile_keys[profile_count], _supportedCached) &&
!IOPMFeatureIsAvailableWithSupportedTable( CFSTR(kIOPMSleepServicesKey),
(CFStringRef)profile_keys[profile_count], _supportedCached))
&& !supportsNewPNKey
)
{
CFDictionaryRemoveValue(this_profile, (CFStringRef)dict_keys[dict_count]);
}
}
else if (CFEqual((CFStringRef)dict_keys[dict_count], CFSTR(kIOPMTCPKeepAlivePrefKey)))
{
CFTypeRef tcpka = kCFBooleanFalse;
IOPlatformCopyFeatureDefault(kIOPlatformTCPKeepAliveDuringSleep, &tcpka);
if (tcpka == kCFBooleanFalse) {
CFDictionaryRemoveValue(this_profile,
(CFStringRef)dict_keys[dict_count]);
}
#endif
}
else if( !IOPMFeatureIsAvailableWithSupportedTable((CFStringRef)dict_keys[dict_count],
(CFStringRef)profile_keys[profile_count], _supportedCached) )
{
CFDictionaryRemoveValue(this_profile,
(CFStringRef)dict_keys[dict_count]);
}
}
free(dict_keys); dict_keys = NULL;
free(dict_vals); dict_vals = NULL;
}
}
exit:
if (dict_keys) {
free(dict_keys);
}
if (dict_vals) {
free(dict_vals);
}
if (profile_keys)
free(profile_keys);
if (profile_vals)
free(profile_vals);
if (_supportedCached)
CFRelease(_supportedCached);
return;
}
IOReturn IOPMActivateSystemPowerSettings( void )
{
return kIOReturnUnsupported;
}
CFDictionaryRef IOPMCopySystemPowerSettings(void)
{
CFDictionaryRef settings = NULL;
settings = CFPreferencesCopyValue(CFSTR(kIOPMSystemPowerSettingsKey),
getGenericPrefsPath(),
kCFPreferencesAnyUser,
kCFPreferencesCurrentHost);
if (isA_CFDictionary(settings)) {
return settings;
}
else {
return NULL;
}
}
IOReturn IOPMSetSystemPowerSetting(CFStringRef key, CFTypeRef value)
{
IOReturn rc = kIOReturnError;
#if !TARGET_OS_EMBEDDED
bool result = false;
CFDictionaryRef settings = NULL;
CFMutableDictionaryRef mutableSettings = NULL;
if ((getuid() != 0) && (geteuid() != 0)) {
return kIOReturnNotPrivileged;
}
settings = IOPMCopySystemPowerSettings();
if (!settings) {
mutableSettings = CFDictionaryCreateMutable(0, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
else {
mutableSettings = CFDictionaryCreateMutableCopy(0, 0, settings);
}
if (!mutableSettings) {
rc = kIOReturnError;
goto exit;
}
CFDictionarySetValue(mutableSettings, key, value);
CFPreferencesSetValue(CFSTR(kIOPMSystemPowerSettingsKey),
mutableSettings, getGenericPrefsPath(),
kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
result = CFPreferencesSynchronize(getGenericPrefsPath(),
kCFPreferencesAnyUser,
kCFPreferencesCurrentHost);
if (result) {
notify_post(kIOPMPrefsChangeNotify);
}
rc = (result ? kIOReturnSuccess : kIOReturnError);
exit:
if (settings) {
CFRelease(settings);
}
if (mutableSettings) {
CFRelease(mutableSettings);
}
#else
(void)key;
(void)value;
#endif
return rc;
}
static void mergeDictIntoMutable(
CFMutableDictionaryRef target,
CFDictionaryRef overrides,
bool overwrite)
{
const CFStringRef *keys = NULL;
const CFTypeRef *objs = NULL;
int count;
int i;
count = CFDictionaryGetCount(overrides);
if(0 == count) return;
keys = (CFStringRef *)malloc(sizeof(CFStringRef) * count);
objs = (CFTypeRef *)malloc(sizeof(CFTypeRef) * count);
if(!keys || !objs) {
goto exit;
}
CFDictionaryGetKeysAndValues(overrides,
(const void **)keys, (const void **)objs);
for(i=0; i<count; i++)
{
if(overwrite) {
CFDictionarySetValue(target, keys[i], objs[i]);
} else {
CFDictionaryAddValue(target, keys[i], objs[i]);
}
}
exit:
if (keys) {
free((void *)keys);
}
if (objs) {
free((void *)objs);
}
}
static CFDictionaryRef getSystemProvidedPreferences(void)
{
CFMutableDictionaryRef systemPrefs = NULL;
CFDictionaryRef overridePrefs = NULL;
CFDictionaryRef acOverride = NULL;
CFDictionaryRef battOverride = NULL;
CFDictionaryRef upsOverride = NULL;
CFDictionaryRef tmp = NULL;
CFMutableDictionaryRef acDict = NULL;
CFMutableDictionaryRef battDict = NULL;
CFMutableDictionaryRef upsDict = NULL;
CFDictionaryRef defaultPrefs = NULL;
io_registry_entry_t regEntry = MACH_PORT_NULL;
bool overrides = false;
bool overrideCopied = false;
regEntry = getPMRootDomainRef();
if (regEntry == MACH_PORT_NULL) {
goto exit;
}
overridePrefs = IORegistryEntryCreateCFProperty(regEntry,
CFSTR(kIOPMSystemDefaultOverrideKey),
kCFAllocatorDefault, 0);
overrides = isA_CFDictionary(overridePrefs);
if (overrides) {
acOverride = CFDictionaryGetValue(overridePrefs, CFSTR(kIOPMACPowerKey));
battOverride = CFDictionaryGetValue(overridePrefs, CFSTR(kIOPMBatteryPowerKey));
upsOverride = CFDictionaryGetValue(overridePrefs, CFSTR(kIOPMUPSPowerKey));
if(!acOverride && !battOverride && !upsOverride)
{
acOverride = CFDictionaryCreateCopy(0,overridePrefs);
battOverride = CFDictionaryCreateCopy(0,overridePrefs);
upsOverride = CFDictionaryCreateCopy(0,overridePrefs);
overrideCopied = true;
} else if (!acOverride || !battOverride || !upsOverride) {
goto exit;
}
overridesSet = true;
}
defaultPrefs = copyDefaultPreferences();
if(!defaultPrefs) {
goto exit;
}
tmp = CFDictionaryGetValue(defaultPrefs, CFSTR(kIOPMACPowerKey));
if (tmp) {
acDict = CFDictionaryCreateMutableCopy(0, CFDictionaryGetCount(tmp), tmp);
if (!acDict) {
goto exit;
}
}
tmp = CFDictionaryGetValue(defaultPrefs, CFSTR(kIOPMBatteryPowerKey));
if (tmp) {
battDict = CFDictionaryCreateMutableCopy(0, CFDictionaryGetCount(tmp), tmp);
if (!battDict) {
goto exit;
}
}
tmp = CFDictionaryGetValue(defaultPrefs, CFSTR(kIOPMUPSPowerKey));
if (tmp) {
upsDict = CFDictionaryCreateMutableCopy(0, CFDictionaryGetCount(tmp), tmp);
if (!upsDict) {
goto exit;
}
}
if (overrides) {
mergeDictIntoMutable(acDict, acOverride, kOverWriteDuplicates);
mergeDictIntoMutable(battDict, battOverride, kOverWriteDuplicates);
mergeDictIntoMutable(upsDict, upsOverride, kOverWriteDuplicates);
}
systemPrefs = CFDictionaryCreateMutable(0,
kPowerSourcesCount,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (!systemPrefs) {
goto exit;
}
CFDictionaryAddValue(systemPrefs, CFSTR(kIOPMACPowerKey), acDict);
CFDictionaryAddValue(systemPrefs, CFSTR(kIOPMBatteryPowerKey), battDict);
CFDictionaryAddValue(systemPrefs, CFSTR(kIOPMUPSPowerKey), upsDict);
exit:
if (overridePrefs) CFRelease(overridePrefs);
if (acDict) CFRelease(acDict);
if (battDict) CFRelease(battDict);
if (upsDict) CFRelease(upsDict);
if (defaultPrefs) CFRelease(defaultPrefs);
if (overrideCopied) {
if (acOverride) {
CFRelease(acOverride);
}
if (battOverride) {
CFRelease(battOverride);
}
if (upsOverride) {
CFRelease(upsOverride);
}
}
return systemPrefs;
}
static CFDictionaryRef copyDefaultPreferences(void)
{
CFMutableDictionaryRef batt = NULL;
CFMutableDictionaryRef ac = NULL;
CFMutableDictionaryRef ups = NULL;
CFMutableDictionaryRef prefs = NULL;
int i;
CFNumberRef val;
CFStringRef key;
batt = CFDictionaryCreateMutable(0, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
ac = CFDictionaryCreateMutable(0, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
ups = CFDictionaryCreateMutable(0, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
for (i=0; i<kPMSettingsCount; i++) {
key = CFStringCreateWithCString(0, defaultSettings[i].keyName, kCFStringEncodingMacRoman);
if (batt) {
val = CFNumberCreate(0, kCFNumberSInt32Type, &defaultSettings[i].defaultValueBattery);
CFDictionarySetValue(batt, key, val);
CFRelease(val);
}
if (ac) {
val = CFNumberCreate(0, kCFNumberSInt32Type, &defaultSettings[i].defaultValueAC);
CFDictionarySetValue(ac, key, val);
CFRelease(val);
}
if (ups) {
val = CFNumberCreate(0, kCFNumberSInt32Type, &defaultSettings[i].defaultValueUPS);
CFDictionarySetValue(ups, key, val);
CFRelease(val);
}
CFRelease(key);
}
if (batt) {
CFDictionarySetValue(batt, CFSTR(kIOHibernateFileKey), CFSTR(kIOHibernateDefaultFile));
}
if (ac) {
CFDictionarySetValue(ac, CFSTR(kIOHibernateFileKey), CFSTR(kIOHibernateDefaultFile));
}
if (ups) {
CFDictionarySetValue(ups, CFSTR(kIOHibernateFileKey), CFSTR(kIOHibernateDefaultFile));
}
prefs = CFDictionaryCreateMutable(0, kPowerSourcesCount,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (prefs) {
CFDictionaryAddValue(prefs, CFSTR(kIOPMACPowerKey), ac);
CFDictionaryAddValue(prefs, CFSTR(kIOPMBatteryPowerKey), batt);
CFDictionaryAddValue(prefs, CFSTR(kIOPMUPSPowerKey), ups);
}
if (ac) {
CFRelease(ac);
}
if (batt) {
CFRelease(batt);
}
if (ups) {
CFRelease(ups);
}
return prefs;
}
CFMutableDictionaryRef copyActivePreferences()
{
CFMutableDictionaryRef prefs = NULL;
CFMutableDictionaryRef tmp = NULL;
CFDictionaryRef acDict = NULL;
CFDictionaryRef battDict = NULL;
CFDictionaryRef upsDict = NULL;
CFDictionaryRef acDef = NULL;
CFDictionaryRef battDef = NULL;
CFDictionaryRef upsDef = NULL;
CFDictionaryRef defaultPrefs = NULL;
acDict = copyPreferencesForSrc(CFSTR(kIOPMACPowerKey));
battDict = copyPreferencesForSrc(CFSTR(kIOPMBatteryPowerKey));
upsDict = copyPreferencesForSrc(CFSTR(kIOPMUPSPowerKey));
prefs = CFDictionaryCreateMutable(0, kPowerSourcesCount,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (!prefs) {
goto exit;
}
defaultPrefs = getSystemProvidedPreferences();
if (!defaultPrefs) {
goto exit;
}
acDef = CFDictionaryGetValue(defaultPrefs, CFSTR(kIOPMACPowerKey));
if (!acDef) {
goto exit;
}
battDef = CFDictionaryGetValue(defaultPrefs, CFSTR(kIOPMBatteryPowerKey));
if (!battDef) {
goto exit;
}
upsDef = CFDictionaryGetValue(defaultPrefs, CFSTR(kIOPMBatteryPowerKey));
if (!upsDef) {
goto exit;
}
if (acDict) {
tmp = CFDictionaryCreateMutableCopy(0, CFDictionaryGetCount(acDict), acDict);
} else {
tmp = CFDictionaryCreateMutable(0, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
if (tmp) {
mergeDictIntoMutable(tmp, acDef, kKeepOriginalValues);
CFDictionarySetValue(prefs, CFSTR(kIOPMACPowerKey), tmp);
CFRelease(tmp);
} else {
goto exit;
}
if (battDict) {
tmp = CFDictionaryCreateMutableCopy(0, CFDictionaryGetCount(battDict), battDict);
} else {
tmp = CFDictionaryCreateMutable(0, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
if (tmp) {
mergeDictIntoMutable(tmp, battDef, kKeepOriginalValues);
CFDictionarySetValue(prefs, CFSTR(kIOPMBatteryPowerKey), tmp);
CFRelease(tmp);
} else {
goto exit;
}
if (upsDict) {
tmp = CFDictionaryCreateMutableCopy(0, CFDictionaryGetCount(upsDict), upsDict);
} else {
tmp = CFDictionaryCreateMutable(0, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
if (tmp) {
mergeDictIntoMutable(tmp, upsDef, kKeepOriginalValues);
CFDictionarySetValue(prefs, CFSTR(kIOPMUPSPowerKey), tmp);
CFRelease(tmp);
} else {
goto exit;
}
IOPMRemoveIrrelevantProperties(prefs);
exit:
if (defaultPrefs) CFRelease(defaultPrefs);
if (acDict) CFRelease(acDict);
if (battDict) CFRelease(battDict);
if (upsDict) CFRelease(upsDict);
return prefs;
}