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;
}