/*
 * native public static long elapsedRealtimeNano();
 */
int64_t elapsedRealtimeNano()
{
#ifdef HAVE_ANDROID_OS
    struct timespec ts;
    int result;
    int64_t timestamp;
#if DEBUG_TIMESTAMP
    static volatile int64_t prevTimestamp;
    static volatile int prevMethod;
#endif

    static int s_fd = -1;

    if (s_fd == -1) {
        int fd = open("/dev/alarm", O_RDONLY);
        if (android_atomic_cmpxchg(-1, fd, &s_fd)) {
            close(fd);
        }
    }

    result = ioctl(s_fd,
            ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts);

    if (result == 0) {
        timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
        checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, METHOD_IOCTL);
        return timestamp;
    }

    // /dev/alarm doesn't exist, fallback to CLOCK_BOOTTIME
    result = clock_gettime(CLOCK_BOOTTIME, &ts);
    if (result == 0) {
        timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
        checkTimeStamps(timestamp, &prevTimestamp, &prevMethod,
                        METHOD_CLOCK_GETTIME);
        return timestamp;
    }

    // XXX: there was an error, probably because the driver didn't
    // exist ... this should return
    // a real error, like an exception!
    timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
    checkTimeStamps(timestamp, &prevTimestamp, &prevMethod,
                    METHOD_SYSTEMTIME);
    return timestamp;
#else
    return systemTime(SYSTEM_TIME_MONOTONIC);
#endif
}
/**
 *  Second out of two main update functions.
 *  Gets triggered by a timer for automatics recompilations.
 *  Can be called both from GLRender or from any other scope.
 */
void SoXipGLSLPrograms::AutoUpdateAction()
{
    bool dirty = false;
    ProgramBatch * batch = 0;

    for (int i = 0; i < mProgramBatchList.getLength(); i++)
    {
        batch = reinterpret_cast<ProgramBatch *>(mProgramBatchList[i]);
        dirty |= checkTimeStamps(&batch->vertShader, vpFilenames[i]);
        dirty |= checkTimeStamps(&batch->geomShader, gpFilenames[i]);
        dirty |= checkTimeStamps(&batch->fragShader, fpFilenames[i]);
    }

    if (dirty)
    {
        mTimedUpdate = true;
        startNotify();
    }
}