Exemplo n.º 1
0
CF_EXPORT SInt32 CFUserNotificationDisplayAlert(CFTimeInterval timeout, CFOptionFlags flags, CFURLRef iconURL, CFURLRef soundURL, CFURLRef localizationURL, CFStringRef alertHeader, CFStringRef alertMessage, CFStringRef defaultButtonTitle, CFStringRef alternateButtonTitle, CFStringRef otherButtonTitle, CFOptionFlags *responseFlags) {
    CHECK_FOR_FORK();
    CFUserNotificationRef userNotification;
    SInt32 retval = ERR_SUCCESS;
    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    if (iconURL) CFDictionaryAddValue(dict, kCFUserNotificationIconURLKey, iconURL);
    if (soundURL) CFDictionaryAddValue(dict, kCFUserNotificationSoundURLKey, soundURL);
    if (localizationURL) CFDictionaryAddValue(dict, kCFUserNotificationLocalizationURLKey, localizationURL);
    if (alertHeader) CFDictionaryAddValue(dict, kCFUserNotificationAlertHeaderKey, alertHeader);
    if (alertMessage) CFDictionaryAddValue(dict, kCFUserNotificationAlertMessageKey, alertMessage);
    if (defaultButtonTitle) CFDictionaryAddValue(dict, kCFUserNotificationDefaultButtonTitleKey, defaultButtonTitle);
    if (alternateButtonTitle) CFDictionaryAddValue(dict, kCFUserNotificationAlternateButtonTitleKey, alternateButtonTitle);
    if (otherButtonTitle) CFDictionaryAddValue(dict, kCFUserNotificationOtherButtonTitleKey, otherButtonTitle);
    userNotification = CFUserNotificationCreate(kCFAllocatorSystemDefault, timeout, flags, &retval, dict);
    if (userNotification) {
        retval = CFUserNotificationReceiveResponse(userNotification, timeout, responseFlags);
        if (MACH_RCV_TIMED_OUT == retval) {
            retval = CFUserNotificationCancel(userNotification);
            if (responseFlags) *responseFlags = kCFUserNotificationCancelResponse;
        }
        CFRelease(userNotification);
    }
    CFRelease(dict);
    return retval;
}
Exemplo n.º 2
0
void
Alert_free(Alert * * alert_p_p)
{
    Alert * alert_p = *alert_p_p;

    if (alert_p) {
	LIST_REMOVE(alert_p, entries);
	if (alert_p->rls) {
	    CFRunLoopSourceInvalidate(alert_p->rls);
	    my_CFRelease(&alert_p->rls);
	}
	if (alert_p->notif) {
	    (void)CFUserNotificationCancel(alert_p->notif);
	    my_CFRelease(&alert_p->notif);
	}
	bzero(alert_p, sizeof(*alert_p));
	free(alert_p);
    }
    *alert_p_p = NULL;
    return;
}
Exemplo n.º 3
0
boolean_t
Alert_update(Alert * alert_p, char * title, char * message)
{
    CFDictionaryRef 		dict = NULL;
    SInt32			error;

    dict = make_alert_dict(title, message);
    if (dict == NULL) {
	goto failed;
    }
    CFUserNotificationCancel(alert_p->notif);
    error = CFUserNotificationUpdate(alert_p->notif, 0, 0, dict);
    my_CFRelease(&dict);
    if (error != 0) {
	EAPLOG_FL(LOG_NOTICE, "CFUserNotificationUpdate failed, %d", error);
	goto failed;
    }
    return (TRUE);

 failed:
    return (FALSE);
}
/* PSLowPowerPSChange
 *
 * Is the handler that gets notified when power source (battery or UPS)
 * state changes. We might respond to this by posting a user notification
 * or performing emergency shutdown.
 */
__private_extern__ void
PSLowPowerPSChange(CFTypeRef ps_blob) 
{
    CFTypeRef           ups = NULL;
    CFDictionaryRef     ups_info = 0;
    int                 t1, t2;
    CFNumberRef         n1, n2;
    int                 minutes_remaining;
    int                 percent_remaining;
    CFBooleanRef        isPresent;
    static int          last_ups_power_source = _kIOUPSExternalPowerBit;
    CFStringRef         power_source = 0;
    CFNumberRef         ups_id = 0;
    
    // Bail immediately if another application (like APC's PowerChute) 
    //   is managing emergency UPS shutdown
    if(!_weManageUPSPower()) {
        goto _exit_PowerSourcesHaveChanged_;
    }
    
    // *** Inspect UPS power levels
    // We assume we're only dealing with 1 UPS for simplicity.
    // The "more than one UPS attached " case is undefined.
    if((ups = IOPSGetActiveUPS(ps_blob)))
    {
        ups_info = isA_CFDictionary(IOPSGetPowerSourceDescription(ps_blob, ups));
        if(!ups_info) goto _exit_PowerSourcesHaveChanged_;

        ups_id = isA_CFNumber(CFDictionaryGetValue(ups_info, CFSTR(kIOPSPowerSourceIDKey)));
        if(!ups_id) goto _exit_PowerSourcesHaveChanged_;
        
        // Check UPS "Is Present" key
        isPresent = isA_CFBoolean(CFDictionaryGetValue(ups_info, CFSTR(kIOPSIsPresentKey)));
        if(!isPresent || !CFBooleanGetValue(isPresent))
        {
#if HAVE_CF_USER_NOTIFICATION
            if(_UPSAlert)
            {
                CFUserNotificationCancel(_UPSAlert);
                _UPSAlert = 0;
            }
#endif
            // If UPS isn't active or connected we shouldn't base policy decisions on it
            goto _exit_PowerSourcesHaveChanged_;
        }
        
        // Check Power Source
        power_source = isA_CFString(CFDictionaryGetValue(ups_info, CFSTR(kIOPSPowerSourceStateKey)));
        if(!power_source || !CFEqual(power_source, CFSTR(kIOPSBatteryPowerValue)))
        {
#if HAVE_CF_USER_NOTIFICATION
            // Running off of AC Power
            if(_UPSAlert)
            {
                CFUserNotificationCancel(_UPSAlert);
                _UPSAlert = 0;
            }
#endif                
            // we have to be draining the internal battery to do a shutdown, so we'll just exit from here.
            goto _exit_PowerSourcesHaveChanged_;
        }
        
        // UPS is running off of internal battery power. Show warning if we just switched from AC to battery.
        if(_kIOUPSExternalPowerBit == last_ups_power_source)
        {
            _switchedToUPSPowerTime = CFAbsoluteTimeGetCurrent();
            
            if( _thresh->haltafter[kHaltEnabled] ) {    
                // If there's a "shutdown after X minutes on UPS power" threshold, 
                // set a timer to remind us to check UPS state again after X minutes
                _reEvaluatePowerSourcesLater(5 + (60*_thresh->haltafter[kHaltValue]));
            }
            
#if HAVE_CF_USER_NOTIFICATION
            if(!_UPSAlert) _UPSAlert = _copyUPSWarning();
#endif 

        }
        
        // TODO: switch this battery-present check for the IOKit 
        //       private API IOPMSystemSupportsUPSShutdown
        // Is an internal battery present?
        if(kCFBooleanTrue == IOPSPowerSourceSupported(ps_blob, CFSTR(kIOPMBatteryPowerKey)))
        {
            // Do not do UPS shutdown if internal battery is present.
            // Internal battery may still be providing power. 
            // Don't do any further UPS shutdown processing.
            // PMU will cause an emergency sleep when the battery runs out - we fall back on that
            // in the battery case.
            goto _exit_PowerSourcesHaveChanged_;                
        }
        
        // ******
        // ****** Perform emergency shutdown if any of the shutdown thresholds is true
        
        // Check to make sure that the UPS has been on battery power for a full 10 seconds before initiating a shutdown.
        // Certain UPS's have reported transient "on battery power with 0% capacity remaining" states for 3-5 seconds.
        // So we make sure not to heed this shutdown notice unless we've been on battery power for 10 seconds.
        if(_secondsSpentOnUPSPower() < 10) {
            _reEvaluatePowerSourcesLater(10);
            goto _exit_PowerSourcesHaveChanged_;
         }
        
        // Calculate battery percentage remaining
        n1 = isA_CFNumber(CFDictionaryGetValue(ups_info, CFSTR(kIOPSCurrentCapacityKey)));
        n2 = isA_CFNumber(CFDictionaryGetValue(ups_info, CFSTR(kIOPSMaxCapacityKey)));
        if(n1 && n2)
        {
            if( CFNumberGetValue(n1, kCFNumberIntType, &t1) &&
                CFNumberGetValue(n2, kCFNumberIntType, &t2)) {
                percent_remaining = (int)(100.0* ((double)t1) / ((double)t2) );
    
                if( _thresh->haltpercent[kHaltEnabled] ) {
                    if( percent_remaining <= _thresh->haltpercent[kHaltValue] ) {
                        _doPowerEmergencyShutdown(ups_id);
                    }
                }
            }
        }
        
        // Get UPS's estimated time remaining
        n1 = isA_CFNumber(CFDictionaryGetValue(ups_info, CFSTR(kIOPSTimeToEmptyKey)));
        if(n1)
        {
            if(CFNumberGetValue(n1, kCFNumberIntType, &minutes_remaining))
            {
                if( _thresh->haltremain[kHaltEnabled] ) {
                    if( minutes_remaining <= _thresh->haltremain[kHaltValue] ) {
                        _doPowerEmergencyShutdown(ups_id);
                    }
                }
            }
        }

        // Determine how long we've been running on UPS power
        if( _thresh->haltafter[kHaltEnabled] ) {
            if(_minutesSpentOnUPSPower() >= _thresh->haltafter[kHaltValue]) {
                _doPowerEmergencyShutdown(ups_id);
            }
        }
        
    } else {
        // No "active UPS" detected. 
        // One could have just disappeared - if we're showing an alert, clear it.
#if HAVE_CF_USER_NOTIFICATION
        if(_UPSAlert)
        {
            CFUserNotificationCancel(_UPSAlert);
            _UPSAlert = 0;
        }
#endif
    }
    
    // exit point
    _exit_PowerSourcesHaveChanged_:
    
    if(power_source && CFEqual(power_source, CFSTR(kIOPSBatteryPowerValue))) {
        last_ups_power_source = _kIOUPSInternalPowerBit;
    } else {
        last_ups_power_source = _kIOUPSExternalPowerBit;
    }
    
    return;
}