Po Lu wrote: > > Also, I don't know how Android records boot time so I'll cc this to Po > > Lu, the main developer for Emacs on Android. > > The boot time is off limits to user programs on Android, for security > reasons.
No, it isn't. The attached file, when compiled and run under Termux (which doesn't have particular permissions), prints e.g.: from clock : 1691616762.476870660 = 2023-08-09 21:32:42.476870660 from sysinfo: 1691616762.329261637 = 2023-08-09 21:32:42.329261637 Note that this uses the kernel's uptime counter, so it will not work well when the user changes the current time manually. But this is rare on Android. Bruno
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <sys/sysinfo.h> static const char * as_time_string (time_t tim) { struct tm *gmt = gmtime (&tim); static char timbuf[100]; if (gmt == NULL || strftime (timbuf, sizeof (timbuf), "%Y-%m-%d %H:%M:%S", gmt) == 0) strcpy (timbuf, "---"); return timbuf; } int main () { /* clock() returns the uptime with a resolution of ca. 1 usec. */ struct timespec ts_now; struct timespec up; if (clock_gettime (CLOCK_REALTIME, &ts_now) == 0 && clock_gettime (CLOCK_BOOTTIME, &up) == 0) { struct timespec result = ts_now; if (result.tv_nsec < up.tv_nsec) { result.tv_nsec += 1000000000; result.tv_sec -= 1; } result.tv_sec -= up.tv_sec; result.tv_nsec -= up.tv_nsec; printf ("from clock : %d.%09d = %s.%09d\n", (int) result.tv_sec, (int) result.tv_nsec, as_time_string (result.tv_sec), (int) result.tv_nsec); } /* /proc/uptime contains the uptime with a resolution of 0.01 sec. */ FILE *fp = fopen ("/proc/uptime", "re"); if (fp != NULL) { char buf[32 + 1]; size_t n = fread (buf, 1, sizeof (buf) - 1, fp); fclose (fp); if (n > 0) { buf[n] = '\0'; /* buf now contains two values: the uptime and the idle time. */ char *endptr; double uptime = strtod (buf, &endptr); if (endptr > buf) { struct timespec result; if (clock_gettime (CLOCK_REALTIME, &result) == 0) { time_t uptime_sec = uptime; struct timespec up = { .tv_sec = uptime_sec, .tv_nsec = (uptime - uptime_sec) * 1e9 + 0.5 }; if (result.tv_nsec < up.tv_nsec) { result.tv_nsec += 1000000000; result.tv_sec -= 1; } result.tv_sec -= up.tv_sec; result.tv_nsec -= up.tv_nsec; printf ("from /proc : %d.%09d = %s.%09d\n", (int) result.tv_sec, (int) result.tv_nsec, as_time_string (result.tv_sec), (int) result.tv_nsec); } } } } /* The sysinfo call returns the uptime with a resolution of 1 sec only. */ struct sysinfo info; if (sysinfo (&info) >= 0) { struct timespec result; if (clock_gettime (CLOCK_REALTIME, &result) == 0) { result.tv_sec -= info.uptime; printf ("from sysinfo: %d.%09d = %s.%09d\n", (int) result.tv_sec, (int) result.tv_nsec, as_time_string (result.tv_sec), (int) result.tv_nsec); } } return 0; }