/* * Copyright (c) 2005-2006 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "PrivateLib.h" #include "PMSettings.h" #include "SetActive.h" #include "powermanagementServer.h" #define kIOPMAppName "Power Management configd plugin" #define kIOPMPrefsPath "com.apple.PowerManagement.xml" #define kAssertionsArraySize 5 #define kIOPMTaskPortKey CFSTR("task") #define kIOPMAssertionsKey CFSTR("assertions") #define kIOPMNumAssertionTypes 4 enum { kHighPerfIndex = 0, kPreventIdleIndex = 1, kDisableInflowIndex = 2, kInhibitChargeIndex = 3 }; // Selectors for AppleSmartBatteryManagerUserClient enum { kSBUCInflowDisable = 0, kSBUCChargeInhibit = 1 }; extern CFMachPortRef serverMachPort; // forward __private_extern__ void cleanupAssertions(mach_port_t dead_port); static void evaluateAssertions(void); static void calculateAggregates(void); static void sendSmartBatteryCommand(uint32_t which, uint32_t level); // globals static CFMutableDictionaryRef assertionsDict = NULL; static int aggregate_assertions[kIOPMNumAssertionTypes]; static int last_aggregate_assertions[kIOPMNumAssertionTypes] = {0, 0, 0, 0}; static CFStringRef assertion_types_arr[kIOPMNumAssertionTypes]; /*********************************** * Static Profiles ***********************************/ static void calculateAggregates(void) { CFDictionaryRef *process_assertions = NULL; int process_count = 0; int i, j; // Clear out the aggregate assertion values. We are about to re-calculate // these values in the big nasty loop below. for(i=0; i= kAssertionsArraySize)) { *return_code = kIOReturnBadArgument; goto exit; } cf_port_for_task = CFMachPortCreateWithPort(0, task, NULL, NULL, 0); if(!cf_port_for_task) { *return_code = kIOReturnNoMemory; goto exit; } calling_task = CFDictionaryGetValue(assertionsDict, cf_port_for_task); if(!calling_task) { *return_code = kIOReturnNotFound; goto exit; } // Retrieve assertions array for the calling task assertions = (CFMutableArrayRef)CFDictionaryGetValue(calling_task, kIOPMAssertionsKey); if(!assertions) { *return_code = kIOReturnInternalError; goto exit; } // Look up assertion at assertion_id and make sure it exists assertion_to_release = CFArrayGetValueAtIndex(assertions, assertion_id); if(!assertion_to_release || !isA_CFDictionary(assertion_to_release)) { *return_code = kIOReturnNotFound; goto exit; } // Release it CFArraySetValueAtIndex(assertions, assertion_id, kCFBooleanFalse); // Check for last reference and cleanup releaseTask = TRUE; n = CFArrayGetCount(assertions); for (i =0; i < n; i++) { CFTypeRef assertion; assertion = CFArrayGetValueAtIndex(assertions, i); if (!CFEqual(assertion, kCFBooleanFalse)) { releaseTask = FALSE; break; } } if (releaseTask) { CFDictionaryRemoveValue(assertionsDict, cf_port_for_task); mach_port_deallocate(mach_task_self(), task); } // Re-evaluate evaluateAssertions(); *return_code = kIOReturnSuccess; exit: if(cf_port_for_task) CFRelease(cf_port_for_task); mach_port_deallocate(mach_task_self(), task); return KERN_SUCCESS; } // Returns a CFDictionary of PM Assertions // * The keys of which are CFNumber (IntType) process ids (pids) // * The values are CFArrays of assertions created by that process // - Each entry in the array is a CFDictionary with: // - key = CFSTR("assert_type"); value = CFStringRef // - key = CFSTR("assert_value"); value = CFNumberRef kern_return_t _io_pm_copy_active_assertions ( mach_port_t server, vm_offset_t *profiles, mach_msg_type_number_t *profilesCnt ) { CFDataRef serialized_object = NULL; CFMachPortRef *task_id_arr = NULL; CFDictionaryRef *task_assertion_dict_arr = NULL; CFMutableDictionaryRef ret_dict = 0; int dict_count; int i; *profiles = 0; *profilesCnt = 0; if(!assertionsDict) goto exit; dict_count = CFDictionaryGetCount(assertionsDict); if(0 == dict_count) goto exit; ret_dict = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); // Iterate our master list of assertions and map them to pids task_id_arr = (CFMachPortRef *)malloc(sizeof(CFMachPortRef)*dict_count); task_assertion_dict_arr = (CFDictionaryRef *)malloc(sizeof(CFDictionaryRef)*dict_count); if(!task_id_arr || !task_assertion_dict_arr) goto exit; CFDictionaryGetKeysAndValues(assertionsDict, (const void **)task_id_arr, (const void **)task_assertion_dict_arr); for(i=0; i