Getting iOS system uptime, that doesn't pause when asleep

Russell Quinn picture Russell Quinn · Sep 19, 2012 · Viewed 18.5k times · Source

I'm looking for a way to get an absolute, always-incrementing system uptime on iOS.

It should return the time since the device was last rebooted, and not be affected by changes to the system date.

All the methods I can find either pause when the device is asleep (CACurrentMediaTime, [NSProcessInfo systemUptime], mach_absolute_time) or are changed when the system date changes (sysctl/KERN_BOOTTIME).

Any ideas?

Answer

Russell Quinn picture Russell Quinn · Sep 19, 2012

I think I worked it out.

time() carries on incrementing while the device is asleep, but of course can be manipulated by the operating system or user. However, the Kernel boottime (a timestamp of when the system last booted) also changes when the system clock is changed, therefore even though both these values are not fixed, the offset between them is.

#include <sys/sysctl.h>

- (time_t)uptime
{
    struct timeval boottime;
    int mib[2] = {CTL_KERN, KERN_BOOTTIME};
    size_t size = sizeof(boottime);
    time_t now;
    time_t uptime = -1;

    (void)time(&now);

    if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 && boottime.tv_sec != 0) {
        uptime = now - boottime.tv_sec;
    }

    return uptime;
}