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 <utils/SystemClock.h> 36 #include <utils/Timers.h> 37 38 #define LOG_TAG "SystemClock" 39 #include "utils/Log.h" 40 41 namespace android { 42 43 /* 44 * Set the current time. This only works when running as root. 45 */ 46 int setCurrentTimeMillis(int64_t millis) 47 { 48 #if WIN32 49 // not implemented 50 return -1; 51 #else 52 struct timeval tv; 53 #ifdef HAVE_ANDROID_OS 54 struct timespec ts; 55 int fd; 56 int res; 57 #endif 58 int ret = 0; 59 60 if (millis <= 0 || millis / 1000LL >= INT_MAX) { 61 return -1; 62 } 63 64 tv.tv_sec = (time_t) (millis / 1000LL); 65 tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL); 66 67 ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec); 68 69 #ifdef HAVE_ANDROID_OS 70 fd = open("/dev/alarm", O_RDWR); 71 if(fd < 0) { 72 ALOGW("Unable to open alarm driver: %s\n", strerror(errno)); 73 return -1; 74 } 75 ts.tv_sec = tv.tv_sec; 76 ts.tv_nsec = tv.tv_usec * 1000; 77 res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts); 78 if(res < 0) { 79 ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno)); 80 ret = -1; 81 } 82 close(fd); 83 #else 84 if (settimeofday(&tv, NULL) != 0) { 85 ALOGW("Unable to set clock to %d.%d: %s\n", 86 (int) tv.tv_sec, (int) tv.tv_usec, strerror(errno)); 87 ret = -1; 88 } 89 #endif 90 91 return ret; 92 #endif // WIN32 93 } 94 95 /* 96 * native public static long uptimeMillis(); 97 */ 98 int64_t uptimeMillis() 99 { 100 int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); 101 return (int64_t) nanoseconds_to_milliseconds(when); 102 } 103 104 /* 105 * native public static long elapsedRealtime(); 106 */ 107 int64_t elapsedRealtime() 108 { 109 #ifdef HAVE_ANDROID_OS 110 static int s_fd = -1; 111 112 if (s_fd == -1) { 113 int fd = open("/dev/alarm", O_RDONLY); 114 if (android_atomic_cmpxchg(-1, fd, &s_fd)) { 115 close(fd); 116 } 117 } 118 119 struct timespec ts; 120 int result = ioctl(s_fd, 121 ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts); 122 123 if (result == 0) { 124 int64_t when = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec; 125 return (int64_t) nanoseconds_to_milliseconds(when); 126 } else { 127 // XXX: there was an error, probably because the driver didn't 128 // exist ... this should return 129 // a real error, like an exception! 130 int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); 131 return (int64_t) nanoseconds_to_milliseconds(when); 132 } 133 #else 134 int64_t when = systemTime(SYSTEM_TIME_MONOTONIC); 135 return (int64_t) nanoseconds_to_milliseconds(when); 136 #endif 137 } 138 139 }; // namespace android 140