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 44 namespace android { 45 46 /* 47 * Set the current time. This only works when running as root. 48 */ 49 static int setCurrentTimeMillis(int64_t millis) 50 { 51 struct timeval tv; 52 struct timespec ts; 53 int fd; 54 int res; 55 int ret = 0; 56 57 if (millis <= 0 || millis / 1000LL >= INT_MAX) { 58 return -1; 59 } 60 61 tv.tv_sec = (time_t) (millis / 1000LL); 62 tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL); 63 64 ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec); 65 66 fd = open("/dev/alarm", O_RDWR); 67 if(fd < 0) { 68 ALOGW("Unable to open alarm driver: %s\n", strerror(errno)); 69 return -1; 70 } 71 ts.tv_sec = tv.tv_sec; 72 ts.tv_nsec = tv.tv_usec * 1000; 73 res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts); 74 if(res < 0) { 75 ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno)); 76 ret = -1; 77 } 78 close(fd); 79 return ret; 80 } 81 82 /* 83 * native public static void setCurrentTimeMillis(long millis) 84 * 85 * Set the current time. This only works when running as root. 86 */ 87 static jboolean android_os_SystemClock_setCurrentTimeMillis(JNIEnv* env, 88 jobject clazz, jlong millis) 89 { 90 return (setCurrentTimeMillis(millis) == 0); 91 } 92 93 /* 94 * native public static long uptimeMillis(); 95 */ 96 static jlong android_os_SystemClock_uptimeMillis(JNIEnv* env, 97 jobject clazz) 98 { 99 return (jlong)uptimeMillis(); 100 } 101 102 /* 103 * native public static long elapsedRealtime(); 104 */ 105 static jlong android_os_SystemClock_elapsedRealtime(JNIEnv* env, 106 jobject clazz) 107 { 108 return (jlong)elapsedRealtime(); 109 } 110 111 /* 112 * native public static long currentThreadTimeMillis(); 113 */ 114 static jlong android_os_SystemClock_currentThreadTimeMillis(JNIEnv* env, 115 jobject clazz) 116 { 117 #if defined(HAVE_POSIX_CLOCKS) 118 struct timespec tm; 119 120 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm); 121 122 return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000; 123 #else 124 struct timeval tv; 125 126 gettimeofday(&tv, NULL); 127 return tv.tv_sec * 1000LL + tv.tv_usec / 1000; 128 #endif 129 } 130 131 /* 132 * native public static long currentThreadTimeMicro(); 133 */ 134 static jlong android_os_SystemClock_currentThreadTimeMicro(JNIEnv* env, 135 jobject clazz) 136 { 137 #if defined(HAVE_POSIX_CLOCKS) 138 struct timespec tm; 139 140 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm); 141 142 return tm.tv_sec * 1000000LL + tm.tv_nsec / 1000; 143 #else 144 struct timeval tv; 145 146 gettimeofday(&tv, NULL); 147 return tv.tv_sec * 1000000LL + tv.tv_nsec / 1000; 148 #endif 149 } 150 151 /* 152 * native public static long currentTimeMicro(); 153 */ 154 static jlong android_os_SystemClock_currentTimeMicro(JNIEnv* env, 155 jobject clazz) 156 { 157 struct timeval tv; 158 159 gettimeofday(&tv, NULL); 160 return tv.tv_sec * 1000000LL + tv.tv_usec; 161 } 162 163 /* 164 * public static native long elapsedRealtimeNano(); 165 */ 166 static jlong android_os_SystemClock_elapsedRealtimeNano(JNIEnv* env, 167 jobject clazz) 168 { 169 return (jlong)elapsedRealtimeNano(); 170 } 171 172 /* 173 * JNI registration. 174 */ 175 static JNINativeMethod gMethods[] = { 176 /* name, signature, funcPtr */ 177 { "setCurrentTimeMillis", "(J)Z", 178 (void*) android_os_SystemClock_setCurrentTimeMillis }, 179 { "uptimeMillis", "()J", 180 (void*) android_os_SystemClock_uptimeMillis }, 181 { "elapsedRealtime", "()J", 182 (void*) android_os_SystemClock_elapsedRealtime }, 183 { "currentThreadTimeMillis", "()J", 184 (void*) android_os_SystemClock_currentThreadTimeMillis }, 185 { "currentThreadTimeMicro", "()J", 186 (void*) android_os_SystemClock_currentThreadTimeMicro }, 187 { "currentTimeMicro", "()J", 188 (void*) android_os_SystemClock_currentTimeMicro }, 189 { "elapsedRealtimeNanos", "()J", 190 (void*) android_os_SystemClock_elapsedRealtimeNano }, 191 }; 192 int register_android_os_SystemClock(JNIEnv* env) 193 { 194 return AndroidRuntime::registerNativeMethods(env, 195 "android/os/SystemClock", gMethods, NELEM(gMethods)); 196 } 197 198 }; // namespace android 199 200