1/* 2 * Copyright (c) 2010 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <CoreFoundation/CoreFoundation.h> 25#include <CoreFoundation/CFPriv.h> 26#include <mach/mach.h> 27#include <IOKit/pwr_mgt/IOPMLib.h> 28#include <IOKit/pwr_mgt/IOPMLibPrivate.h> 29#include "IOSystemConfiguration.h" 30#include <sys/time.h> 31#include <notify.h> 32 33#include "powermanagement_mig.h" 34#include "powermanagement.h" 35 36#include <servers/bootstrap.h> 37 38 39#define kAssertionsArraySize 5 40 41#ifndef __CFRunLoopOptionsTakeAssertion 42#define __CFRunLoopOptionsTakeAssertion 8 43#endif 44 45#ifndef __CFRunLoopOptionsDropAssertion 46#define __CFRunLoopOptionsDropAssertion 9 47#endif 48 49static const int kMaxNameLength = 128; 50 51IOReturn _pm_connect(mach_port_t *newConnection); 52IOReturn _pm_disconnect(mach_port_t connection); 53 54 55__private_extern__ IOReturn _copyPMServerObject(int selector, int assertionID, CFTypeRef *objectOut); 56__private_extern__ io_registry_entry_t getPMRootDomainRef(void); 57 58 59/****************************************************************************** 60 * IOPMAssertionCreate 61 * 62 * Deprecated but still supported wrapper for IOPMAssertionCreateWithProperties 63 ******************************************************************************/ 64IOReturn IOPMAssertionCreate( 65 CFStringRef AssertionType, 66 IOPMAssertionLevel AssertionLevel, 67 IOPMAssertionID *AssertionID) 68{ 69 return IOPMAssertionCreateWithName(AssertionType, AssertionLevel, 70 CFSTR("Nameless (via IOPMAssertionCreate)"), AssertionID); 71} 72 73/****************************************************************************** 74 * IOPMAssertionCreateWithName 75 * 76 * Deprecated but still supported wrapper for IOPMAssertionCreateWithProperties 77 ******************************************************************************/ 78IOReturn IOPMAssertionCreateWithName( 79 CFStringRef AssertionType, 80 IOPMAssertionLevel AssertionLevel __unused, 81 CFStringRef AssertionName, 82 IOPMAssertionID *AssertionID) 83{ 84 CFMutableDictionaryRef properties = NULL; 85 IOReturn result = kIOReturnError; 86 87 if (!AssertionName || !AssertionID || !AssertionType) 88 return kIOReturnBadArgument; 89 90 properties = CFDictionaryCreateMutable(0, 3, &kCFTypeDictionaryKeyCallBacks, 91 &kCFTypeDictionaryValueCallBacks); 92 93 if (properties) 94 { 95 96 CFDictionarySetValue(properties, kIOPMAssertionTypeKey, AssertionType); 97 98 CFDictionarySetValue(properties, kIOPMAssertionNameKey, AssertionName); 99 100 CFDictionarySetValue(properties, kIOPMAssertionUsedDeprecatedCreateAPIKey, kCFBooleanTrue); 101 102 result = IOPMAssertionCreateWithProperties(properties, AssertionID); 103 104 CFRelease(properties); 105 } 106 107 return result; 108} 109 110/****************************************************************************** 111 * IOPMAssertionCreateWithDescription 112 * 113 ******************************************************************************/ 114 115IOReturn IOPMAssertionCreateWithDescription( 116 CFStringRef AssertionType, 117 CFStringRef Name, 118 CFStringRef Details, 119 CFStringRef HumanReadableReason, 120 CFStringRef LocalizationBundlePath, 121 CFTimeInterval Timeout, 122 CFStringRef TimeoutAction, 123 IOPMAssertionID *AssertionID) 124{ 125 CFMutableDictionaryRef descriptor = NULL; 126 IOReturn ret = kIOReturnError; 127 128 if (!AssertionType || !Name || !AssertionID) { 129 ret = kIOReturnBadArgument; 130 goto exit; 131 } 132 133 descriptor = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 134 if (!descriptor) { 135 goto exit; 136 } 137 138 CFDictionarySetValue(descriptor, kIOPMAssertionNameKey, Name); 139 140 CFDictionarySetValue(descriptor, kIOPMAssertionTypeKey, AssertionType); 141 142 if (Details) { 143 CFDictionarySetValue(descriptor, kIOPMAssertionDetailsKey, Details); 144 } 145 if (HumanReadableReason) { 146 CFDictionarySetValue(descriptor, kIOPMAssertionHumanReadableReasonKey, HumanReadableReason); 147 } 148 if (LocalizationBundlePath) { 149 CFDictionarySetValue(descriptor, kIOPMAssertionLocalizationBundlePathKey, LocalizationBundlePath); 150 } 151 if (Timeout) { 152 CFNumberRef Timeout_num = CFNumberCreate(0, kCFNumberDoubleType, &Timeout); 153 CFDictionarySetValue(descriptor, kIOPMAssertionTimeoutKey, Timeout_num); 154 CFRelease(Timeout_num); 155 } 156 if (TimeoutAction) { 157 CFDictionarySetValue(descriptor, kIOPMAssertionTimeoutActionKey, TimeoutAction); 158 } 159 160 ret = IOPMAssertionCreateWithProperties(descriptor, AssertionID); 161 162 CFRelease(descriptor); 163 164exit: 165 return ret; 166} 167 168/****************************************************************************** 169 * IOPMAssertionCreateWithProperties 170 * 171 ******************************************************************************/ 172IOReturn IOPMAssertionCreateWithProperties( 173 CFDictionaryRef AssertionProperties, 174 IOPMAssertionID *AssertionID) 175{ 176 IOReturn return_code = kIOReturnError; 177 kern_return_t kern_result = KERN_SUCCESS; 178 mach_port_t pm_server = MACH_PORT_NULL; 179 IOReturn err; 180 CFDataRef flattenedProps = NULL; 181 CFStringRef assertionTypeString = NULL; 182 CFMutableDictionaryRef mutableProps = NULL; 183 int disableAppSleep = 0; 184#if !TARGET_OS_IPHONE 185 static int disableAppSleepToken = 0; 186 static int enableAppSleepToken = 0; 187#else 188 static int resyncToken = 0; 189 static CFMutableDictionaryRef resyncCopy = NULL; 190#endif 191 192 if (!AssertionProperties || !AssertionID) { 193 return_code = kIOReturnBadArgument; 194 goto exit; 195 } 196 197 mutableProps = CFDictionaryCreateMutableCopy(NULL, 0, AssertionProperties); 198 if (!mutableProps) { 199 return_code = kIOReturnInternalError; 200 goto exit; 201 } 202 203 err = _pm_connect(&pm_server); 204 if(kIOReturnSuccess != err) { 205 return_code = kIOReturnInternalError; 206 goto exit; 207 } 208 209 210 assertionTypeString = CFDictionaryGetValue(AssertionProperties, kIOPMAssertionTypeKey); 211 212 213#if TARGET_OS_IPHONE 214 215 if (isA_CFString(assertionTypeString) && 216 CFEqual(assertionTypeString, kIOPMAssertionTypeEnableIdleSleep) && !resyncToken) { 217 218 resyncCopy = CFDictionaryCreateMutableCopy(NULL, 0, AssertionProperties); 219 notify_register_dispatch( kIOUserAssertionReSync, 220 &resyncToken, dispatch_get_main_queue(), 221 ^(int t __unused) { 222 IOPMAssertionID id; 223 IOPMAssertionCreateWithProperties(resyncCopy, &id); 224 }); 225 } 226#endif 227 flattenedProps = CFPropertyListCreateData(0, mutableProps, 228 kCFPropertyListBinaryFormat_v1_0, 0, NULL /* error */); 229 if (!flattenedProps) { 230 return_code = kIOReturnBadArgument; 231 goto exit; 232 } 233 234#if !TARGET_OS_IPHONE 235 if ( !disableAppSleepToken ) { 236 char notify_str[128]; 237 238 snprintf(notify_str, sizeof(notify_str), "%s.%d", 239 kIOPMDisableAppSleepPrefix, getpid()); 240 241 notify_register_dispatch( 242 notify_str, 243 &disableAppSleepToken, 244 dispatch_get_main_queue(), 245 ^(int t __unused){ 246 __CFRunLoopSetOptionsReason(__CFRunLoopOptionsTakeAssertion, CFSTR("App is holding power assertion.")); 247 }); 248 } 249 250 if ( !enableAppSleepToken ) { 251 char notify_str[128]; 252 253 snprintf(notify_str, sizeof(notify_str), "%s.%d", 254 kIOPMEnableAppSleepPrefix, getpid()); 255 256 notify_register_dispatch( 257 notify_str, 258 &enableAppSleepToken, 259 dispatch_get_main_queue(), 260 ^(int t __unused){ 261 __CFRunLoopSetOptionsReason(__CFRunLoopOptionsDropAssertion, CFSTR("App released all power assertions.")); 262 }); 263 } 264#endif 265 266 kern_result = io_pm_assertion_create( pm_server, 267 (vm_offset_t)CFDataGetBytePtr(flattenedProps), 268 CFDataGetLength(flattenedProps), 269 (int *)AssertionID, 270 &disableAppSleep, 271 &return_code); 272 273 if(KERN_SUCCESS != kern_result) { 274 return_code = kIOReturnInternalError; 275 } 276#if !TARGET_OS_IPHONE 277 if (disableAppSleep) { 278 __CFRunLoopSetOptionsReason(__CFRunLoopOptionsTakeAssertion, 279 CFSTR("App is preventing system sleep with power assertion.")); 280 } 281#endif 282 283exit: 284 if (flattenedProps) { 285 CFRelease(flattenedProps); 286 } 287 288 if (MACH_PORT_NULL != pm_server) { 289 _pm_disconnect(pm_server); 290 } 291 292 if (mutableProps) 293 CFRelease(mutableProps); 294 return return_code; 295} 296 297/****************************************************************************** 298 * IOPMAssertionsRetain 299 * 300 ******************************************************************************/ 301void IOPMAssertionRetain(IOPMAssertionID theAssertion) 302{ 303 IOReturn return_code = kIOReturnError; 304 kern_return_t kern_result = KERN_SUCCESS; 305 mach_port_t pm_server = MACH_PORT_NULL; 306 IOReturn err; 307 int disableAppSleep = 0; 308 int enableAppSleep = 0; 309 310 if (!theAssertion) { 311 return_code = kIOReturnBadArgument; 312 goto exit; 313 } 314 315 err = _pm_connect(&pm_server); 316 if(kIOReturnSuccess != err) { 317 return_code = kIOReturnInternalError; 318 goto exit; 319 } 320 321 kern_result = io_pm_assertion_retain_release( pm_server, 322 (int)theAssertion, 323 kIOPMAssertionMIGDoRetain, 324 &disableAppSleep, 325 &enableAppSleep, 326 &return_code); 327 328 if(KERN_SUCCESS != kern_result) { 329 return_code = kIOReturnInternalError; 330 } 331#if !TARGET_OS_IPHONE 332 if (disableAppSleep) { 333 __CFRunLoopSetOptionsReason(__CFRunLoopOptionsTakeAssertion, 334 CFSTR("App is preventing system sleep with power assertion.")); 335 } 336#endif 337 338 339exit: 340 if (MACH_PORT_NULL != pm_server) { 341 _pm_disconnect(pm_server); 342 } 343 return; 344} 345 346 347/****************************************************************************** 348 * IOPMAssertionsRelease 349 * 350 ******************************************************************************/ 351IOReturn IOPMAssertionRelease(IOPMAssertionID AssertionID) 352{ 353 IOReturn return_code = kIOReturnError; 354 kern_return_t kern_result = KERN_SUCCESS; 355 mach_port_t pm_server = MACH_PORT_NULL; 356 IOReturn err; 357 int disableAppSleep = 0; 358 int enableAppSleep = 0; 359 360 if (!AssertionID) { 361 return_code = kIOReturnBadArgument; 362 goto exit; 363 } 364 365 err = _pm_connect(&pm_server); 366 if(kIOReturnSuccess != err) { 367 return_code = kIOReturnInternalError; 368 goto exit; 369 } 370 371 kern_result = io_pm_assertion_retain_release( pm_server, 372 (int)AssertionID, 373 kIOPMAssertionMIGDoRelease, 374 &disableAppSleep, 375 &enableAppSleep, 376 &return_code); 377 378 if(KERN_SUCCESS != kern_result) { 379 return_code = kIOReturnInternalError; 380 } 381#if !TARGET_OS_IPHONE 382 if (enableAppSleep) { 383 __CFRunLoopSetOptionsReason(__CFRunLoopOptionsDropAssertion, 384 CFSTR("App is not preventing sleep any more.")); 385 } 386#endif 387 388 _pm_disconnect(pm_server); 389exit: 390 return return_code; 391} 392 393 394/****************************************************************************** 395 * IOPMAssertionSetProperty 396 * 397 ******************************************************************************/ 398IOReturn IOPMAssertionSetProperty(IOPMAssertionID theAssertion, CFStringRef theProperty, CFTypeRef theValue) 399{ 400 IOReturn return_code = kIOReturnError; 401 kern_return_t kern_result = KERN_SUCCESS; 402 mach_port_t pm_server = MACH_PORT_NULL; 403 CFDataRef sendData = NULL; 404 CFDictionaryRef sendDict = NULL; 405 int disableAppSleep = 0; 406 int enableAppSleep = 0; 407 408 if (!theAssertion) { 409 return_code = kIOReturnBadArgument; 410 goto exit; 411 } 412 413 return_code = _pm_connect(&pm_server); 414 415 if(kIOReturnSuccess != return_code) { 416 goto exit; 417 } 418 419 sendDict = CFDictionaryCreate(0, (const void **)&theProperty, (const void **)&theValue, 1, 420 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 421 422 if (sendDict) { 423 sendData = CFPropertyListCreateData(0, sendDict, kCFPropertyListBinaryFormat_v1_0, 0, NULL /* error */); 424 CFRelease(sendDict); 425 } 426 427 428 kern_result = io_pm_assertion_set_properties(pm_server, 429 (int)theAssertion, 430 (vm_offset_t)CFDataGetBytePtr(sendData), 431 CFDataGetLength(sendData), 432 &disableAppSleep, 433 &enableAppSleep, 434 (int *)&return_code); 435 436 if(KERN_SUCCESS != kern_result) { 437 return_code = kIOReturnInternalError; 438 goto exit; 439 } 440#if !TARGET_OS_IPHONE 441 if (disableAppSleep) { 442 __CFRunLoopSetOptionsReason(__CFRunLoopOptionsTakeAssertion, 443 CFSTR("App is preventing system sleep with power assertion.")); 444 } 445 else if (enableAppSleep) { 446 __CFRunLoopSetOptionsReason(__CFRunLoopOptionsDropAssertion, 447 CFSTR("App is not preventing sleep any more.")); 448 } 449#endif 450 451 452exit: 453 if (sendData) 454 CFRelease(sendData); 455 456 if (MACH_PORT_NULL != pm_server) { 457 _pm_disconnect(pm_server); 458 } 459 return return_code; 460} 461 462/****************************************************************************** 463 * IOPMAssertionSetTimeout 464 * 465 ******************************************************************************/ 466IOReturn IOPMAssertionSetTimeout(IOPMAssertionID whichAssertion, 467 CFTimeInterval timeoutInterval) 468{ 469 IOReturn return_code = kIOReturnError; 470 CFNumberRef intervalNum = NULL; 471 int timeoutSecs = (int)timeoutInterval; 472 473 intervalNum = CFNumberCreate(0, kCFNumberIntType, &timeoutSecs); 474 475 if (intervalNum) 476 { 477 return_code = IOPMAssertionSetProperty(whichAssertion, kIOPMAssertionTimeoutKey, intervalNum); 478 479 CFRelease(intervalNum); 480 } 481 482 return return_code; 483} 484 485/****************************************************************************** 486 * IOPMAssertionDeclareNotificationEvent 487 * 488 ******************************************************************************/ 489 IOReturn IOPMAssertionDeclareNotificationEvent( 490 __unused CFStringRef notificationName, 491 __unused CFTimeInterval secondsToDisplay, 492 __unused IOPMAssertionID *AssertionID) 493{ 494#if TCPKEEPALIVE 495 IOPMAssertionID id = kIOPMNullAssertionID; 496 IOReturn ret = kIOReturnSuccess; 497 io_registry_entry_t rootdomain = getPMRootDomainRef(); 498 CFBooleanRef lidIsClosed = NULL; 499 CFBooleanRef desktopMode = NULL; 500 501 if (rootdomain == MACH_PORT_NULL) 502 return kIOReturnInternalError; 503 504 desktopMode = IORegistryEntryCreateCFProperty(rootdomain, 505 CFSTR("DesktopMode"), kCFAllocatorDefault, 0); 506 lidIsClosed = IORegistryEntryCreateCFProperty(rootdomain, 507 CFSTR(kAppleClamshellStateKey), kCFAllocatorDefault, 0); 508 509 if ((kCFBooleanTrue == lidIsClosed) && (kCFBooleanFalse == desktopMode)) { 510 ret = kIOReturnNotReady; 511 goto exit; 512 } 513 514 ret = IOPMAssertionCreateWithDescription( 515 kIOPMAssertDisplayWake, 516 notificationName, NULL, NULL, NULL, 517 secondsToDisplay, kIOPMAssertionTimeoutActionRelease, 518 &id); 519 if (AssertionID) 520 *AssertionID = id; 521 522exit: 523 if (lidIsClosed) CFRelease(lidIsClosed); 524 if (desktopMode) CFRelease(desktopMode); 525 526 return ret; 527#endif 528 if (AssertionID) { 529 *AssertionID = kIOPMNullAssertionID; 530 } 531 return kIOReturnUnsupported; 532} 533 534/****************************************************************************** 535 * IOPMAssertionDeclareSystemActivity 536 * 537 ******************************************************************************/ 538IOReturn IOPMAssertionDeclareSystemActivity( 539 CFStringRef AssertionName, 540 IOPMAssertionID *AssertionID, 541 IOPMSystemState *SystemState) 542{ 543 IOReturn return_code = kIOReturnError; 544 mach_port_t pm_server = MACH_PORT_NULL; 545 kern_return_t kern_result = KERN_SUCCESS; 546 IOReturn err; 547 548 CFMutableDictionaryRef properties = NULL; 549 CFDataRef flattenedProps = NULL; 550 551 if (!AssertionName || !AssertionID || !SystemState) { 552 return_code = kIOReturnBadArgument; 553 goto exit; 554 } 555 556 err = _pm_connect(&pm_server); 557 if(kIOReturnSuccess != err) { 558 return_code = kIOReturnInternalError; 559 goto exit; 560 } 561 562 properties = CFDictionaryCreateMutable(0, 1, &kCFTypeDictionaryKeyCallBacks, 563 &kCFTypeDictionaryValueCallBacks); 564 CFDictionarySetValue(properties, kIOPMAssertionNameKey, AssertionName); 565 566 flattenedProps = CFPropertyListCreateData(0, properties, 567 kCFPropertyListBinaryFormat_v1_0, 0, NULL /* error */); 568 if (!flattenedProps) { 569 return_code = kIOReturnBadArgument; 570 goto exit; 571 } 572 573 kern_result = io_pm_declare_system_active( 574 pm_server, 575 (int *)SystemState, 576 (vm_offset_t)CFDataGetBytePtr(flattenedProps), 577 CFDataGetLength(flattenedProps), 578 (int *)AssertionID, 579 &return_code); 580 581 if(KERN_SUCCESS != kern_result) { 582 return_code = kIOReturnInternalError; 583 goto exit; 584 } 585exit: 586 if (flattenedProps) 587 CFRelease(flattenedProps); 588 589 if (properties) 590 CFRelease(properties); 591 592 if (MACH_PORT_NULL != pm_server) { 593 _pm_disconnect(pm_server); 594 } 595 596 return return_code; 597 598} 599/****************************************************************************** 600 * IOPMAssertionDeclareUserActivity 601 * 602 ******************************************************************************/ 603IOReturn IOPMAssertionDeclareUserActivity( 604 CFStringRef AssertionName, 605 IOPMUserActiveType userType, 606 IOPMAssertionID *AssertionID) 607{ 608 609 IOReturn return_code = kIOReturnError; 610 mach_port_t pm_server = MACH_PORT_NULL; 611 kern_return_t kern_result = KERN_SUCCESS; 612 IOReturn err; 613 static struct timeval prev_ts = {0,0}; 614 struct timeval ts; 615 int disableAppSleep = 0; 616 617 618 CFMutableDictionaryRef properties = NULL; 619 CFDataRef flattenedProps = NULL; 620 621 if (!AssertionName || !AssertionID) { 622 return_code = kIOReturnBadArgument; 623 goto exit; 624 } 625 626 gettimeofday(&ts, NULL); 627 if (ts.tv_sec - prev_ts.tv_sec <= 5) { 628 if ( *AssertionID == kIOPMNullAssertionID ) 629 *AssertionID = 0xabcd; /* Give a dummy id */ 630 return_code = kIOReturnSuccess; 631 goto exit; 632 } 633 prev_ts = ts; 634 635 err = _pm_connect(&pm_server); 636 if(kIOReturnSuccess != err) { 637 return_code = kIOReturnInternalError; 638 goto exit; 639 } 640 641 properties = CFDictionaryCreateMutable(0, 1, &kCFTypeDictionaryKeyCallBacks, 642 &kCFTypeDictionaryValueCallBacks); 643 CFDictionarySetValue(properties, kIOPMAssertionNameKey, AssertionName); 644 645 flattenedProps = CFPropertyListCreateData(0, properties, 646 kCFPropertyListBinaryFormat_v1_0, 0, NULL /* error */); 647 if (!flattenedProps) { 648 return_code = kIOReturnBadArgument; 649 goto exit; 650 } 651 652 653 kern_result = io_pm_declare_user_active( 654 pm_server, 655 userType, 656 (vm_offset_t)CFDataGetBytePtr(flattenedProps), 657 CFDataGetLength(flattenedProps), 658 (int *)AssertionID, 659 &disableAppSleep, 660 &return_code); 661 662 663 if(KERN_SUCCESS != kern_result) { 664 return_code = kIOReturnInternalError; 665 goto exit; 666 } 667#if !TARGET_OS_IPHONE 668 if (disableAppSleep) { 669 __CFRunLoopSetOptionsReason(__CFRunLoopOptionsTakeAssertion, 670 CFSTR("App is preventing system sleep with power assertion.")); 671 } 672#endif 673 674 675exit: 676 if (flattenedProps) 677 CFRelease(flattenedProps); 678 679 if (properties) 680 CFRelease(properties); 681 682 if (MACH_PORT_NULL != pm_server) { 683 _pm_disconnect(pm_server); 684 } 685 686 return return_code; 687} 688 689 690/****************************************************************************** 691 * IOPMDeclareNetworkClientActivity 692 * 693 ******************************************************************************/ 694IOReturn IOPMDeclareNetworkClientActivity( 695 CFStringRef AssertionName, 696 IOPMAssertionID *AssertionID) 697{ 698 699 IOReturn return_code = kIOReturnError; 700 mach_port_t pm_server = MACH_PORT_NULL; 701 kern_return_t kern_result = KERN_SUCCESS; 702 IOReturn err; 703 int disableAppSleep = 0; 704 705 706 CFMutableDictionaryRef properties = NULL; 707 CFDataRef flattenedProps = NULL; 708 709 if (!AssertionName || !AssertionID) { 710 return_code = kIOReturnBadArgument; 711 goto exit; 712 } 713 714 err = _pm_connect(&pm_server); 715 if(kIOReturnSuccess != err) { 716 return_code = kIOReturnInternalError; 717 goto exit; 718 } 719 720 properties = CFDictionaryCreateMutable(0, 1, &kCFTypeDictionaryKeyCallBacks, 721 &kCFTypeDictionaryValueCallBacks); 722 CFDictionarySetValue(properties, kIOPMAssertionNameKey, AssertionName); 723 724 flattenedProps = CFPropertyListCreateData(0, properties, 725 kCFPropertyListBinaryFormat_v1_0, 0, NULL /* error */); 726 if (!flattenedProps) { 727 return_code = kIOReturnBadArgument; 728 goto exit; 729 } 730 731 732 kern_result = io_pm_declare_network_client_active( 733 pm_server, 734 (vm_offset_t)CFDataGetBytePtr(flattenedProps), 735 CFDataGetLength(flattenedProps), 736 (int *)AssertionID, 737 &disableAppSleep, 738 &return_code); 739 740 741 if(KERN_SUCCESS != kern_result) { 742 return_code = kIOReturnInternalError; 743 goto exit; 744 } 745#if !TARGET_OS_IPHONE 746 if (disableAppSleep) { 747 __CFRunLoopSetOptionsReason(__CFRunLoopOptionsTakeAssertion, 748 CFSTR("App is preventing system sleep with power assertion.")); 749 } 750#endif 751 752 753exit: 754 if (flattenedProps) 755 CFRelease(flattenedProps); 756 757 if (properties) 758 CFRelease(properties); 759 760 if (MACH_PORT_NULL != pm_server) { 761 _pm_disconnect(pm_server); 762 } 763 764 return return_code; 765} 766 767 768 769/****************************************************************************** 770 * IOPMCopyAssertionsByProcess 771 * 772 ******************************************************************************/ 773IOReturn IOPMCopyAssertionsByProcess(CFDictionaryRef *AssertionsByPid) 774{ 775 IOReturn return_code = kIOReturnError; 776 CFArrayRef flattenedDictionary = NULL; 777 int flattenedArrayCount = 0; 778 CFNumberRef *newDictKeys = NULL; 779 CFArrayRef *newDictValues = NULL; 780 781 if (!AssertionsByPid) 782 return kIOReturnBadArgument; 783 784 return_code = _copyPMServerObject(kIOPMAssertionMIGCopyAll, 0, (CFTypeRef *)&flattenedDictionary); 785 786 if (kIOReturnSuccess != return_code) 787 goto exit; 788 789 /* 790 * This API returns a dictionary whose keys are process ID's. 791 * This is perfectly acceptable in CoreFoundation, EXCEPT that you cannot 792 * serialize a dictionary with CFNumbers for keys using CF or IOKit 793 * serialization. 794 * 795 * To serialize this dictionary and pass it from configd to the caller's process, 796 * we re-formatted it as a "flattened" array of dictionaries in configd, 797 * and we will re-constitute with pid's for keys here. 798 * 799 * Next time around, I will simply not use CFNumberRefs for keys in API. 800 */ 801 802 803 if (flattenedDictionary) { 804 flattenedArrayCount = CFArrayGetCount(flattenedDictionary); 805 } 806 807 if (0 == flattenedArrayCount) { 808 goto exit; 809 } 810 811 newDictKeys = (CFNumberRef *)malloc(sizeof(CFTypeRef) * flattenedArrayCount); 812 newDictValues = (CFArrayRef *)malloc(sizeof(CFTypeRef) * flattenedArrayCount); 813 814 if (!newDictKeys || !newDictValues) 815 goto exit; 816 817 for (int i=0; i < flattenedArrayCount; i++) 818 { 819 CFDictionaryRef dictionaryAtIndex = NULL; 820 821 if ((dictionaryAtIndex = CFArrayGetValueAtIndex(flattenedDictionary, i))) 822 { 823 824 newDictKeys[i] = CFDictionaryGetValue(dictionaryAtIndex, kIOPMAssertionPIDKey); 825 newDictValues[i] = CFDictionaryGetValue(dictionaryAtIndex, CFSTR("PerTaskAssertions")); 826 } 827 } 828 829 *AssertionsByPid = CFDictionaryCreate(kCFAllocatorDefault, 830 (const void **)newDictKeys, (const void **)newDictValues, flattenedArrayCount, 831 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 832 833 return_code = kIOReturnSuccess; 834 835exit: 836 if (newDictKeys) 837 free(newDictKeys); 838 if (newDictValues) 839 free(newDictValues); 840 if (flattenedDictionary) 841 CFRelease(flattenedDictionary); 842 return return_code; 843} 844 845/****************************************************************************** 846 * IOPMAssertionCopyProperties 847 * 848 ******************************************************************************/ 849CFDictionaryRef IOPMAssertionCopyProperties(IOPMAssertionID theAssertion) 850{ 851 CFDictionaryRef theResult = NULL; 852 853 _copyPMServerObject(kIOPMAssertionMIGCopyOneAssertionProperties, theAssertion, (CFTypeRef *)&theResult); 854 855 return theResult; 856} 857 858/****************************************************************************** 859 * IOPMCopyTimedOutAssertions 860 * 861 ******************************************************************************/ 862IOReturn IOPMCopyTimedOutAssertions(CFArrayRef *timedOutAssertions) 863{ 864 if (!timedOutAssertions) 865 return kIOReturnBadArgument; 866 867 return _copyPMServerObject(kIOPMAssertionMIGCopyTimedOutAssertions, 0, (CFTypeRef *)timedOutAssertions); 868} 869 870/****************************************************************************** 871 * IOPMCopyAssertionsStatus 872 * 873 ******************************************************************************/ 874IOReturn IOPMCopyAssertionsStatus(CFDictionaryRef *AssertionsStatus) 875{ 876 if (!AssertionsStatus) 877 return kIOReturnBadArgument; 878 879 return _copyPMServerObject(kIOPMAssertionMIGCopyStatus, 0, (CFTypeRef *)AssertionsStatus); 880} 881 882/****************************************************************************** 883 * _copyPMServerObject 884 * 885 ******************************************************************************/ 886__private_extern__ IOReturn _copyPMServerObject(int selector, int assertionID, CFTypeRef *objectOut) 887{ 888 IOReturn return_code = kIOReturnError; 889 kern_return_t kern_result = KERN_SUCCESS; 890 mach_port_t pm_server = MACH_PORT_NULL; 891 vm_offset_t theResultsPtr = 0; 892 mach_msg_type_number_t theResultsCnt = 0; 893 CFDataRef theResultData = NULL; 894 895 *objectOut = NULL; 896 897 if(kIOReturnSuccess != (return_code = _pm_connect(&pm_server))) { 898 return kIOReturnNotFound; 899 } 900 901 kern_result = io_pm_assertion_copy_details(pm_server, assertionID, selector, 902 &theResultsPtr, &theResultsCnt, &return_code); 903 904 if(KERN_SUCCESS != kern_result) { 905 return kIOReturnInternalError; 906 } 907 908 if (return_code != kIOReturnSuccess) 909 return return_code; 910 911 if ((theResultData = CFDataCreate(0, (const UInt8 *)theResultsPtr, (CFIndex)theResultsCnt))) 912 { 913 *objectOut = CFPropertyListCreateWithData(0, theResultData, kCFPropertyListImmutable, NULL, NULL); 914 CFRelease(theResultData); 915 } 916 917 if (theResultsPtr && 0 != theResultsCnt) { 918 vm_deallocate(mach_task_self(), theResultsPtr, theResultsCnt); 919 } 920 921 if (MACH_PORT_NULL != pm_server) { 922 _pm_disconnect(pm_server); 923 } 924 925 return kIOReturnSuccess; 926} 927 928