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 46/* 47 * Set the current time. This only works when running as root. 48 */ 49static 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 */ 87static 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 */ 96static 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 */ 105static 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 */ 114static 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 */ 134static 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 */ 154static 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 */ 166static jlong android_os_SystemClock_elapsedRealtimeNano(JNIEnv* env, 167 jobject clazz) 168{ 169 return (jlong)elapsedRealtimeNano(); 170} 171 172/* 173 * JNI registration. 174 */ 175static 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}; 192int 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