6

What is the difference between kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionTypePreventSystemSleep and kIOPMAssertionTypePreventUserIdleSystemSleep?

I am trying to create an IOPMAssertion that will prevent the mac from going to sleep autommatically but I really can't tell which of these I should use. I'm getting confused with their descriptions and cannot make sense of them (see the docs for this).

If you're curious, this is how I'm doing it in code:

IOReturn success = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, CFSTR("My app is running"), &preventSleepAssertionID);

if (success != kIOReturnSuccess) {
    NSLog(@"Could not create sleep prevention assertion");
}
Alex
  • 5,009
  • 3
  • 39
  • 73

2 Answers2

2

Apple have published a Q&A note on this subject, which I believe answers your question. The key comments in the example code in question:

// kIOPMAssertionTypeNoDisplaySleep prevents display sleep,
// kIOPMAssertionTypeNoIdleSleep prevents idle sleep

The former prevents the screen dimming or turning off entirely. Use this if your app is going to be used in a way where the user won't be using the keyboard and mouse, e.g. video player or video chat.

The latter prevents the system itself from going to sleep, but allows the screen to dim and eventually switch off entirely. Useful for long-running computations and apps that only need e.g. audio.

The actual code mirrors what you've got:

//reasonForActivity is a descriptive string used by the system whenever it needs 
//  to tell the user why the system is not sleeping. For example, 
//  "Mail Compacting Mailboxes" would be a useful string.

//  NOTE: IOPMAssertionCreateWithName limits the string to 128 characters. 
CFStringRef* reasonForActivity= CFSTR("Describe Activity Type");

IOPMAssertionID assertionID;
IOReturn success = IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, 
                                    kIOPMAssertionLevelOn, reasonForActivity, &assertionID); 
if (success == kIOReturnSuccess)
{

    //Add the work you need to do without 
    //  the system sleeping here.

    success = IOPMAssertionRelease(assertionID);
    //The system will be able to sleep again. 
}

Power assertions can still be overridden by the user triggering sleep explicitly (e.g. closing the lid or selecting it in the  menu) or if the system is on battery power.

Are you having trouble getting your code to work?

pmdj
  • 22,018
  • 3
  • 52
  • 103
  • Thanks, this is what I wanted to know. About getting it to work... I think it is working, but frankly it's difficult to see if the computer is going to sleep or not. There's another function that lists all current assertions (which I can't remember right now) and using that I can see my assertion is there. But like I said: actually testing if the computer goes to sleep or not isn't easy. – Alex Jul 21 '13 at 10:53
  • If the computer is not asleep, you should be able to ping it from another machine on the network. – pmdj Jul 21 '13 at 12:07
  • This does not explain the difference between `kIOPMAssertionTypeNoIdleSleep`, `kIOPMAssertionTypePreventSystemSleep` and `kIOPMAssertionTypePreventUserIdleSystemSleep` as originally asked. – augurar Feb 07 '21 at 20:15
1

The documentation for each value gives more information about what they do.

kIOPMAssertionTypePreventUserIdleSystemSleep

Prevents the system from sleeping automatically due to a lack of user activity. ... The system may still sleep for lid close, Apple menu, low battery, or other sleep reasons. This assertion does not put the system into Dark Wake.

kIOPMAssertionTypeNoIdleSleep

The system will not idle sleep when enabled. Note that the system may sleep for other reasons. ... the system will prefer to enter the Dark Wake state, or remain in Dark Wake if already there, rather than go to sleep.

kIOPMAssertionTypePreventSystemSleep

Prevents the system from sleeping and allows the system to reside in Dark Wake for an arbitrary length of time. ... the system will prefer to enter the Dark Wake state, or remain in Dark Wake if already there, rather than go to sleep.

This wording seems to imply that the first option prevents idle sleep due to lack of activity, the second option does the same but prefers to enter Dark Wake rather than sleep, and the third option entirely prevents sleep in favor of Dark Wake.

Looking at PMAssertions.c in the power management code, along with IOPMrootDomain.cpp in the iokit kernel code, it appears that kIOPMAssertionTypeNoIdleSleep is treated as an alias for kIOPMAssertionTypePreventUserIdleSystemSleep, whereas kIOPMAssertionTypePreventSystemSleep is handled differently. Setting kIOPMAssertionTypePreventSystemSleep creates a kernel assertion that entirely prevents system sleep except in extreme cases such as low battery or thermal emergency. Also, this only applies when the computer is connected to external power, unless a special flag is set.

In practice, it appears most Mac applications use kIOPMAssertionTypePreventUserIdleSystemSleep to prevent sleep while performing background tasks. For example Time Machine sets an assertion of this type while backing up. One exception is Internet Sharing, which uses kIOPMAssertionTypePreventSystemSleep to keep the computer awake indefinitely when connected to external power. Note that some users may find this behavior unexpected or undesirable.[1][2]

In summary:

  • If you want to prevent the computer from sleeping due to inactivity, use kIOPMAssertionTypePreventUserIdleSystemSleep.
  • Avoid using kIOPMAssertionTypePreventSystemSleep unless you have a reason to entirely prevent system sleep.
augurar
  • 12,081
  • 6
  • 50
  • 65