1 /* //device/libs/android_runtime/android_server_AlarmManagerService.cpp
3 ** Copyright 2006, The Android Open Source Project
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
9 ** http://www.apache.org/licenses/LICENSE-2.0
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
18 #define LOG_TAG "AlarmManagerService"
22 #include <utils/Log.h>
23 #include <utils/misc.h>
24 #include <utils/String8.h>
30 #include <sys/epoll.h>
31 #include <sys/timerfd.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <arpa/inet.h>
35 #include <netinet/in.h>
39 #include <linux/ioctl.h>
40 #include <linux/android_alarm.h>
41 #include <linux/rtc.h>
43 #if HAVE_QC_TIME_SERVICES
45 #include <private/time_genoff.h>
51 static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1;
52 static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = {
60 /* to match the legacy alarm driver implementation, we need an extra
61 CLOCK_REALTIME fd which exists specifically to be canceled on RTC changes */
66 AlarmImpl(int *fds, size_t n_fds);
69 virtual int set(int type, struct timespec *ts) = 0;
70 virtual int clear(int type, struct timespec *ts) = 0;
71 virtual int setTime(struct timeval *tv) = 0;
72 virtual int waitForAlarm() = 0;
79 class AlarmImplAlarmDriver : public AlarmImpl
82 AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }
84 int set(int type, struct timespec *ts);
85 int clear(int type, struct timespec *ts);
86 int setTime(struct timeval *tv);
90 class AlarmImplTimerFd : public AlarmImpl
93 AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd, int rtc_id) :
94 AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd), rtc_id(rtc_id) { }
97 int set(int type, struct timespec *ts);
98 int clear(int type, struct timespec *ts);
99 int setTime(struct timeval *tv);
107 AlarmImpl::AlarmImpl(int *fds_, size_t n_fds) : fds(new int[n_fds]),
110 memcpy(fds, fds_, n_fds * sizeof(fds[0]));
113 AlarmImpl::~AlarmImpl()
115 for (size_t i = 0; i < n_fds; i++) {
121 int AlarmImplAlarmDriver::set(int type, struct timespec *ts)
123 return ioctl(fds[0], ANDROID_ALARM_SET(type), ts);
126 int AlarmImplAlarmDriver::clear(int type, struct timespec *ts)
128 return ioctl(fds[0], ANDROID_ALARM_CLEAR(type), ts);
131 #if HAVE_QC_TIME_SERVICES
132 static int setTimeServicesTime(time_bases_type base, long int secs)
135 time_genoff_info_type time_set;
136 uint64_t value = secs;
137 time_set.base = base;
138 time_set.unit = TIME_SECS;
139 time_set.operation = T_SET;
140 time_set.ts_val = &value;
141 rc = time_genoff_operation(&time_set);
143 ALOGE("Error setting generic offset: %d. Still setting system time\n", rc);
150 int AlarmImplAlarmDriver::setTime(struct timeval *tv)
155 ts.tv_sec = tv->tv_sec;
156 ts.tv_nsec = tv->tv_usec * 1000;
157 res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts);
158 #if HAVE_QC_TIME_SERVICES
159 setTimeServicesTime(ATS_USER, (tv->tv_sec));
163 ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
167 int AlarmImplAlarmDriver::waitForAlarm()
169 return ioctl(fds[0], ANDROID_ALARM_WAIT);
172 AlarmImplTimerFd::~AlarmImplTimerFd()
174 for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
175 epoll_ctl(epollfd, EPOLL_CTL_DEL, fds[i], NULL);
180 int AlarmImplTimerFd::set(int type, struct timespec *ts)
182 if (type > ANDROID_ALARM_TYPE_COUNT) {
187 if (!ts->tv_nsec && !ts->tv_sec) {
190 /* timerfd interprets 0 = disarm, so replace with a practically
191 equivalent deadline of 1 ns */
193 struct itimerspec spec;
194 memset(&spec, 0, sizeof(spec));
195 memcpy(&spec.it_value, ts, sizeof(spec.it_value));
197 return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
200 int AlarmImplTimerFd::clear(int type, struct timespec *ts)
202 if (type > ANDROID_ALARM_TYPE_COUNT) {
210 struct itimerspec spec;
211 memset(&spec, 0, sizeof(spec));
212 memcpy(&spec.it_value, ts, sizeof(spec.it_value));
214 return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
217 int AlarmImplTimerFd::setTime(struct timeval *tv)
220 struct tm tm, *gmtime_res;
224 res = settimeofday(tv, NULL);
226 ALOGV("settimeofday() failed: %s\n", strerror(errno));
231 ALOGV("Not setting RTC because wall clock RTC was not found");
236 android::String8 rtc_dev = String8::format("/dev/rtc%d", rtc_id);
237 fd = open(rtc_dev.string(), O_RDWR);
239 ALOGV("Unable to open %s: %s\n", rtc_dev.string(), strerror(errno));
243 gmtime_res = gmtime_r(&tv->tv_sec, &tm);
245 ALOGV("gmtime_r() failed: %s\n", strerror(errno));
250 memset(&rtc, 0, sizeof(rtc));
251 rtc.tm_sec = tm.tm_sec;
252 rtc.tm_min = tm.tm_min;
253 rtc.tm_hour = tm.tm_hour;
254 rtc.tm_mday = tm.tm_mday;
255 rtc.tm_mon = tm.tm_mon;
256 rtc.tm_year = tm.tm_year;
257 rtc.tm_wday = tm.tm_wday;
258 rtc.tm_yday = tm.tm_yday;
259 rtc.tm_isdst = tm.tm_isdst;
260 res = ioctl(fd, RTC_SET_TIME, &rtc);
262 ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
268 int AlarmImplTimerFd::waitForAlarm()
270 epoll_event events[N_ANDROID_TIMERFDS];
272 int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1);
278 for (int i = 0; i < nevents; i++) {
279 uint32_t alarm_idx = events[i].data.u32;
281 ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused));
283 if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) {
284 result |= ANDROID_ALARM_TIME_CHANGE_MASK;
289 result |= (1 << alarm_idx);
296 static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
298 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
302 if (millis <= 0 || millis / 1000LL >= INT_MAX) {
306 tv.tv_sec = (time_t) (millis / 1000LL);
307 tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
309 ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
311 ret = impl->setTime(&tv);
314 ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
320 static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
324 tz.tz_minuteswest = minswest;
327 int result = settimeofday(NULL, &tz);
329 ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno));
332 ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest);
338 static jlong init_alarm_driver()
340 int fd = open("/dev/alarm", O_RDWR);
342 ALOGV("opening alarm driver failed: %s", strerror(errno));
346 AlarmImpl *ret = new AlarmImplAlarmDriver(fd);
347 return reinterpret_cast<jlong>(ret);
350 static const char rtc_sysfs[] = "/sys/class/rtc";
352 static bool rtc_is_hctosys(unsigned int rtc_id)
354 android::String8 hctosys_path = String8::format("%s/rtc%u/hctosys",
357 FILE *file = fopen(hctosys_path.string(), "re");
359 ALOGE("failed to open %s: %s", hctosys_path.string(), strerror(errno));
363 unsigned int hctosys;
365 int err = fscanf(file, "%u", &hctosys);
367 ALOGE("failed to read from %s: %s", hctosys_path.string(),
370 ALOGE("%s did not have expected contents", hctosys_path.string());
378 static int wall_clock_rtc()
380 DIR *dir = opendir(rtc_sysfs);
382 ALOGE("failed to open %s: %s", rtc_sysfs, strerror(errno));
386 struct dirent *dirent;
387 while (errno = 0, dirent = readdir(dir)) {
389 int matched = sscanf(dirent->d_name, "rtc%u", &rtc_id);
393 else if (matched != 1)
396 if (rtc_is_hctosys(rtc_id)) {
397 ALOGV("found wall clock RTC %u", rtc_id);
403 ALOGW("no wall clock RTC found");
405 ALOGE("failed to enumerate RTCs: %s", strerror(errno));
410 static jlong init_timerfd()
413 int fds[N_ANDROID_TIMERFDS];
415 epollfd = epoll_create(N_ANDROID_TIMERFDS);
417 ALOGV("epoll_create(%zu) failed: %s", N_ANDROID_TIMERFDS,
422 for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
423 fds[i] = timerfd_create(android_alarm_to_clockid[i], 0);
425 ALOGV("timerfd_create(%u) failed: %s", android_alarm_to_clockid[i],
428 for (size_t j = 0; j < i; j++) {
435 AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd, wall_clock_rtc());
437 for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
439 event.events = EPOLLIN | EPOLLWAKEUP;
442 int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event);
444 ALOGV("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno));
450 struct itimerspec spec;
451 memset(&spec, 0, sizeof(spec));
452 /* 0 = disarmed; the timerfd doesn't need to be armed to get
453 RTC change notifications, just set up as cancelable */
455 int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT],
456 TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL);
458 ALOGV("timerfd_settime() failed: %s", strerror(errno));
463 return reinterpret_cast<jlong>(ret);
466 static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject)
468 jlong ret = init_alarm_driver();
473 return init_timerfd();
476 static void android_server_AlarmManagerService_close(JNIEnv*, jobject, jlong nativeData)
478 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
482 static void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds)
484 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
487 ts.tv_nsec = nanoseconds;
489 int result = impl->set(type, &ts);
492 ALOGE("Unable to set alarm to %lld.%09lld: %s\n",
493 static_cast<long long>(seconds),
494 static_cast<long long>(nanoseconds), strerror(errno));
498 static void android_server_AlarmManagerService_clear(JNIEnv*, jobject, jlong nativeData, jint type,
499 jlong seconds, jlong nanoseconds)
501 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
504 ts.tv_nsec = nanoseconds;
506 int result = impl->clear(type, &ts);
509 ALOGE("Unable to clear alarm %lld.%09lld: %s\n",
510 static_cast<long long>(seconds),
511 static_cast<long long>(nanoseconds), strerror(errno));
515 static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jlong nativeData)
517 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
522 result = impl->waitForAlarm();
523 } while (result < 0 && errno == EINTR);
527 ALOGE("Unable to wait on alarm: %s\n", strerror(errno));
534 static JNINativeMethod sMethods[] = {
535 /* name, signature, funcPtr */
536 {"init", "()J", (void*)android_server_AlarmManagerService_init},
537 {"close", "(J)V", (void*)android_server_AlarmManagerService_close},
538 {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
539 {"clear", "(JIJJ)V", (void*)android_server_AlarmManagerService_clear},
540 {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
541 {"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},
542 {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
545 int register_android_server_AlarmManagerService(JNIEnv* env)
547 return jniRegisterNativeMethods(env, "com/android/server/AlarmManagerService",
548 sMethods, NELEM(sMethods));
551 } /* namespace android */