android_os_SystemClock.cpp revision b7bbca2d6a0ba8e7a0cee5f7683a8193c0e30140
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18/* 19 * System clock functions. 20 */ 21 22#ifdef HAVE_ANDROID_OS 23#include <linux/ioctl.h> 24#include <linux/rtc.h> 25#include <utils/Atomic.h> 26#include <linux/android_alarm.h> 27#endif 28 29#include <sys/time.h> 30#include <limits.h> 31#include <fcntl.h> 32#include <errno.h> 33#include <string.h> 34 35#include "JNIHelp.h" 36#include "jni.h" 37#include "android_runtime/AndroidRuntime.h" 38 39#include <sys/time.h> 40#include <time.h> 41 42#include <utils/SystemClock.h> 43 44namespace android { 45 46static int setCurrentTimeMillisAlarmDriver(struct timeval *tv) 47{ 48 struct timespec ts; 49 int fd; 50 int res; 51 52 fd = open("/dev/alarm", O_RDWR); 53 if(fd < 0) { 54 ALOGV("Unable to open alarm driver: %s\n", strerror(errno)); 55 return -1; 56 } 57 ts.tv_sec = tv->tv_sec; 58 ts.tv_nsec = tv->tv_usec * 1000; 59 res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts); 60 if (res < 0) 61 ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno)); 62 close(fd); 63 return res; 64} 65 66static int setCurrentTimeMillisRtc(struct timeval *tv) 67{ 68 struct rtc_time rtc; 69 struct tm tm, *gmtime_res; 70 int fd; 71 int res; 72 73 fd = open("/dev/rtc0", O_RDWR); 74 if (fd < 0) { 75 ALOGV("Unable to open RTC driver: %s\n", strerror(errno)); 76 return -1; 77 } 78 79 res = settimeofday(tv, NULL); 80 if (res < 0) { 81 ALOGV("settimeofday() failed: %s\n", strerror(errno)); 82 goto done; 83 } 84 85 gmtime_res = gmtime_r(&tv->tv_sec, &tm); 86 if (!gmtime_res) { 87 ALOGV("gmtime_r() failed: %s\n", strerror(errno)); 88 res = -1; 89 goto done; 90 } 91 92 memset(&rtc, 0, sizeof(rtc)); 93 rtc.tm_sec = tm.tm_sec; 94 rtc.tm_min = tm.tm_min; 95 rtc.tm_hour = tm.tm_hour; 96 rtc.tm_mday = tm.tm_mday; 97 rtc.tm_mon = tm.tm_mon; 98 rtc.tm_year = tm.tm_year; 99 rtc.tm_wday = tm.tm_wday; 100 rtc.tm_yday = tm.tm_yday; 101 rtc.tm_isdst = tm.tm_isdst; 102 res = ioctl(fd, RTC_SET_TIME, &rtc); 103 if (res < 0) 104 ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno)); 105done: 106 close(fd); 107 return res; 108} 109 110/* 111 * Set the current time. This only works when running as root. 112 */ 113static int setCurrentTimeMillis(int64_t millis) 114{ 115 struct timeval tv; 116 int ret; 117 118 if (millis <= 0 || millis / 1000LL >= INT_MAX) { 119 return -1; 120 } 121 122 tv.tv_sec = (time_t) (millis / 1000LL); 123 tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL); 124 125 ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec); 126 127 ret = setCurrentTimeMillisAlarmDriver(&tv); 128 if (ret < 0) 129 ret = setCurrentTimeMillisRtc(&tv); 130 131 if(ret < 0) { 132 ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno)); 133 ret = -1; 134 } 135 return ret; 136} 137 138/* 139 * native public static void setCurrentTimeMillis(long millis) 140 * 141 * Set the current time. This only works when running as root. 142 */ 143static jboolean android_os_SystemClock_setCurrentTimeMillis(JNIEnv* env, 144 jobject clazz, jlong millis) 145{ 146 return (setCurrentTimeMillis(millis) == 0); 147} 148 149/* 150 * native public static long uptimeMillis(); 151 */ 152static jlong android_os_SystemClock_uptimeMillis(JNIEnv* env, 153 jobject clazz) 154{ 155 return (jlong)uptimeMillis(); 156} 157 158/* 159 * native public static long elapsedRealtime(); 160 */ 161static jlong android_os_SystemClock_elapsedRealtime(JNIEnv* env, 162 jobject clazz) 163{ 164 return (jlong)elapsedRealtime(); 165} 166 167/* 168 * native public static long currentThreadTimeMillis(); 169 */ 170static jlong android_os_SystemClock_currentThreadTimeMillis(JNIEnv* env, 171 jobject clazz) 172{ 173#if defined(HAVE_POSIX_CLOCKS) 174 struct timespec tm; 175 176 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm); 177 178 return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000; 179#else 180 struct timeval tv; 181 182 gettimeofday(&tv, NULL); 183 return tv.tv_sec * 1000LL + tv.tv_usec / 1000; 184#endif 185} 186 187/* 188 * native public static long currentThreadTimeMicro(); 189 */ 190static jlong android_os_SystemClock_currentThreadTimeMicro(JNIEnv* env, 191 jobject clazz) 192{ 193#if defined(HAVE_POSIX_CLOCKS) 194 struct timespec tm; 195 196 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm); 197 198 return tm.tv_sec * 1000000LL + tm.tv_nsec / 1000; 199#else 200 struct timeval tv; 201 202 gettimeofday(&tv, NULL); 203 return tv.tv_sec * 1000000LL + tv.tv_nsec / 1000; 204#endif 205} 206 207/* 208 * native public static long currentTimeMicro(); 209 */ 210static jlong android_os_SystemClock_currentTimeMicro(JNIEnv* env, 211 jobject clazz) 212{ 213 struct timeval tv; 214 215 gettimeofday(&tv, NULL); 216 return tv.tv_sec * 1000000LL + tv.tv_usec; 217} 218 219/* 220 * public static native long elapsedRealtimeNano(); 221 */ 222static jlong android_os_SystemClock_elapsedRealtimeNano(JNIEnv* env, 223 jobject clazz) 224{ 225 return (jlong)elapsedRealtimeNano(); 226} 227 228/* 229 * JNI registration. 230 */ 231static JNINativeMethod gMethods[] = { 232 /* name, signature, funcPtr */ 233 { "setCurrentTimeMillis", "(J)Z", 234 (void*) android_os_SystemClock_setCurrentTimeMillis }, 235 { "uptimeMillis", "()J", 236 (void*) android_os_SystemClock_uptimeMillis }, 237 { "elapsedRealtime", "()J", 238 (void*) android_os_SystemClock_elapsedRealtime }, 239 { "currentThreadTimeMillis", "()J", 240 (void*) android_os_SystemClock_currentThreadTimeMillis }, 241 { "currentThreadTimeMicro", "()J", 242 (void*) android_os_SystemClock_currentThreadTimeMicro }, 243 { "currentTimeMicro", "()J", 244 (void*) android_os_SystemClock_currentTimeMicro }, 245 { "elapsedRealtimeNanos", "()J", 246 (void*) android_os_SystemClock_elapsedRealtimeNano }, 247}; 248int register_android_os_SystemClock(JNIEnv* env) 249{ 250 return AndroidRuntime::registerNativeMethods(env, 251 "android/os/SystemClock", gMethods, NELEM(gMethods)); 252} 253 254}; // namespace android 255 256