OSDN Git Service

4025988
[android-x86/frameworks-base.git] /
1 /* //device/libs/android_runtime/android_server_AlarmManagerService.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
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
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
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.
16 */
17
18 #define LOG_TAG "AlarmManagerService"
19
20 #include "JNIHelp.h"
21 #include "jni.h"
22 #include <utils/Log.h>
23 #include <utils/misc.h>
24 #include <utils/String8.h>
25
26 #include <dirent.h>
27 #include <fcntl.h>
28 #include <stdio.h>
29 #include <string.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>
36 #include <stdlib.h>
37 #include <errno.h>
38 #include <unistd.h>
39 #include <linux/ioctl.h>
40 #include <linux/android_alarm.h>
41 #include <linux/rtc.h>
42
43 #if HAVE_QC_TIME_SERVICES
44 extern "C" {
45 #include <private/time_genoff.h>
46 }
47 #endif
48
49 namespace android {
50
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] = {
53     CLOCK_REALTIME_ALARM,
54     CLOCK_REALTIME,
55     CLOCK_BOOTTIME_ALARM,
56     CLOCK_BOOTTIME,
57     CLOCK_MONOTONIC,
58     CLOCK_REALTIME,
59 };
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 */
62
63 class AlarmImpl
64 {
65 public:
66     AlarmImpl(int *fds, size_t n_fds);
67     virtual ~AlarmImpl();
68
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;
73
74 protected:
75     int *fds;
76     size_t n_fds;
77 };
78
79 class AlarmImplAlarmDriver : public AlarmImpl
80 {
81 public:
82     AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }
83
84     int set(int type, struct timespec *ts);
85     int clear(int type, struct timespec *ts);
86     int setTime(struct timeval *tv);
87     int waitForAlarm();
88 };
89
90 class AlarmImplTimerFd : public AlarmImpl
91 {
92 public:
93     AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd, int rtc_id) :
94         AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd), rtc_id(rtc_id) { }
95     ~AlarmImplTimerFd();
96
97     int set(int type, struct timespec *ts);
98     int clear(int type, struct timespec *ts);
99     int setTime(struct timeval *tv);
100     int waitForAlarm();
101
102 private:
103     int epollfd;
104     int rtc_id;
105 };
106
107 AlarmImpl::AlarmImpl(int *fds_, size_t n_fds) : fds(new int[n_fds]),
108         n_fds(n_fds)
109 {
110     memcpy(fds, fds_, n_fds * sizeof(fds[0]));
111 }
112
113 AlarmImpl::~AlarmImpl()
114 {
115     for (size_t i = 0; i < n_fds; i++) {
116         close(fds[i]);
117     }
118     delete [] fds;
119 }
120
121 int AlarmImplAlarmDriver::set(int type, struct timespec *ts)
122 {
123     return ioctl(fds[0], ANDROID_ALARM_SET(type), ts);
124 }
125
126 int AlarmImplAlarmDriver::clear(int type, struct timespec *ts)
127 {
128     return ioctl(fds[0], ANDROID_ALARM_CLEAR(type), ts);
129 }
130
131 #if HAVE_QC_TIME_SERVICES
132 static int setTimeServicesTime(time_bases_type base, long int secs)
133 {
134     int rc = 0;
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);
142     if (rc) {
143         ALOGE("Error setting generic offset: %d. Still setting system time\n", rc);
144         rc = -1;
145     }
146     return rc;
147 }
148 #endif
149
150 int AlarmImplAlarmDriver::setTime(struct timeval *tv)
151 {
152     struct timespec ts;
153     int res;
154
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));
160 #endif
161
162     if (res < 0)
163         ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
164     return res;
165 }
166
167 int AlarmImplAlarmDriver::waitForAlarm()
168 {
169     return ioctl(fds[0], ANDROID_ALARM_WAIT);
170 }
171
172 AlarmImplTimerFd::~AlarmImplTimerFd()
173 {
174     for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
175         epoll_ctl(epollfd, EPOLL_CTL_DEL, fds[i], NULL);
176     }
177     close(epollfd);
178 }
179
180 int AlarmImplTimerFd::set(int type, struct timespec *ts)
181 {
182     if (type > ANDROID_ALARM_TYPE_COUNT) {
183         errno = EINVAL;
184         return -1;
185     }
186
187     if (!ts->tv_nsec && !ts->tv_sec) {
188         ts->tv_nsec = 1;
189     }
190     /* timerfd interprets 0 = disarm, so replace with a practically
191        equivalent deadline of 1 ns */
192
193     struct itimerspec spec;
194     memset(&spec, 0, sizeof(spec));
195     memcpy(&spec.it_value, ts, sizeof(spec.it_value));
196
197     return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
198 }
199
200 int AlarmImplTimerFd::clear(int type, struct timespec *ts)
201 {
202     if (type > ANDROID_ALARM_TYPE_COUNT) {
203         errno = EINVAL;
204         return -1;
205     }
206
207     ts->tv_sec = 0;
208     ts->tv_nsec = 0;
209
210     struct itimerspec spec;
211     memset(&spec, 0, sizeof(spec));
212     memcpy(&spec.it_value, ts, sizeof(spec.it_value));
213
214     return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
215 }
216
217 int AlarmImplTimerFd::setTime(struct timeval *tv)
218 {
219     struct rtc_time rtc;
220     struct tm tm, *gmtime_res;
221     int fd;
222     int res;
223
224     res = settimeofday(tv, NULL);
225     if (res < 0) {
226         ALOGV("settimeofday() failed: %s\n", strerror(errno));
227         return -1;
228     }
229
230     if (rtc_id < 0) {
231         ALOGV("Not setting RTC because wall clock RTC was not found");
232         errno = ENODEV;
233         return -1;
234     }
235
236     android::String8 rtc_dev = String8::format("/dev/rtc%d", rtc_id);
237     fd = open(rtc_dev.string(), O_RDWR);
238     if (fd < 0) {
239         ALOGV("Unable to open %s: %s\n", rtc_dev.string(), strerror(errno));
240         return res;
241     }
242
243     gmtime_res = gmtime_r(&tv->tv_sec, &tm);
244     if (!gmtime_res) {
245         ALOGV("gmtime_r() failed: %s\n", strerror(errno));
246         res = -1;
247         goto done;
248     }
249
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);
261     if (res < 0)
262         ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
263 done:
264     close(fd);
265     return res;
266 }
267
268 int AlarmImplTimerFd::waitForAlarm()
269 {
270     epoll_event events[N_ANDROID_TIMERFDS];
271
272     int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1);
273     if (nevents < 0) {
274         return nevents;
275     }
276
277     int result = 0;
278     for (int i = 0; i < nevents; i++) {
279         uint32_t alarm_idx = events[i].data.u32;
280         uint64_t unused;
281         ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused));
282         if (err < 0) {
283             if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) {
284                 result |= ANDROID_ALARM_TIME_CHANGE_MASK;
285             } else {
286                 return err;
287             }
288         } else {
289             result |= (1 << alarm_idx);
290         }
291     }
292
293     return result;
294 }
295
296 static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
297 {
298     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
299     struct timeval tv;
300     int ret;
301
302     if (millis <= 0 || millis / 1000LL >= INT_MAX) {
303         return -1;
304     }
305
306     tv.tv_sec = (time_t) (millis / 1000LL);
307     tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
308
309     ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
310
311     ret = impl->setTime(&tv);
312
313     if(ret < 0) {
314         ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
315         ret = -1;
316     }
317     return ret;
318 }
319
320 static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
321 {
322     struct timezone tz;
323
324     tz.tz_minuteswest = minswest;
325     tz.tz_dsttime = 0;
326
327     int result = settimeofday(NULL, &tz);
328     if (result < 0) {
329         ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno));
330         return -1;
331     } else {
332         ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest);
333     }
334
335     return 0;
336 }
337
338 static jlong init_alarm_driver()
339 {
340     int fd = open("/dev/alarm", O_RDWR);
341     if (fd < 0) {
342         ALOGV("opening alarm driver failed: %s", strerror(errno));
343         return 0;
344     }
345
346     AlarmImpl *ret = new AlarmImplAlarmDriver(fd);
347     return reinterpret_cast<jlong>(ret);
348 }
349
350 static const char rtc_sysfs[] = "/sys/class/rtc";
351
352 static bool rtc_is_hctosys(unsigned int rtc_id)
353 {
354     android::String8 hctosys_path = String8::format("%s/rtc%u/hctosys",
355             rtc_sysfs, rtc_id);
356
357     FILE *file = fopen(hctosys_path.string(), "re");
358     if (!file) {
359         ALOGE("failed to open %s: %s", hctosys_path.string(), strerror(errno));
360         return false;
361     }
362
363     unsigned int hctosys;
364     bool ret = false;
365     int err = fscanf(file, "%u", &hctosys);
366     if (err == EOF)
367         ALOGE("failed to read from %s: %s", hctosys_path.string(),
368                 strerror(errno));
369     else if (err == 0)
370         ALOGE("%s did not have expected contents", hctosys_path.string());
371     else
372         ret = hctosys;
373
374     fclose(file);
375     return ret;
376 }
377
378 static int wall_clock_rtc()
379 {
380     DIR *dir = opendir(rtc_sysfs);
381     if (!dir) {
382         ALOGE("failed to open %s: %s", rtc_sysfs, strerror(errno));
383         return -1;
384     }
385
386     struct dirent *dirent;
387     while (errno = 0, dirent = readdir(dir)) {
388         unsigned int rtc_id;
389         int matched = sscanf(dirent->d_name, "rtc%u", &rtc_id);
390
391         if (matched < 0)
392             break;
393         else if (matched != 1)
394             continue;
395
396         if (rtc_is_hctosys(rtc_id)) {
397             ALOGV("found wall clock RTC %u", rtc_id);
398             return rtc_id;
399         }
400     }
401
402     if (errno == 0)
403         ALOGW("no wall clock RTC found");
404     else
405         ALOGE("failed to enumerate RTCs: %s", strerror(errno));
406
407     return -1;
408 }
409
410 static jlong init_timerfd()
411 {
412     int epollfd;
413     int fds[N_ANDROID_TIMERFDS];
414
415     epollfd = epoll_create(N_ANDROID_TIMERFDS);
416     if (epollfd < 0) {
417         ALOGV("epoll_create(%zu) failed: %s", N_ANDROID_TIMERFDS,
418                 strerror(errno));
419         return 0;
420     }
421
422     for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
423         fds[i] = timerfd_create(android_alarm_to_clockid[i], 0);
424         if (fds[i] < 0) {
425             ALOGV("timerfd_create(%u) failed: %s",  android_alarm_to_clockid[i],
426                     strerror(errno));
427             close(epollfd);
428             for (size_t j = 0; j < i; j++) {
429                 close(fds[j]);
430             }
431             return 0;
432         }
433     }
434
435     AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd, wall_clock_rtc());
436
437     for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
438         epoll_event event;
439         event.events = EPOLLIN | EPOLLWAKEUP;
440         event.data.u32 = i;
441
442         int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event);
443         if (err < 0) {
444             ALOGV("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno));
445             delete ret;
446             return 0;
447         }
448     }
449
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 */
454
455     int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT],
456             TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL);
457     if (err < 0) {
458         ALOGV("timerfd_settime() failed: %s", strerror(errno));
459         delete ret;
460         return 0;
461     }
462
463     return reinterpret_cast<jlong>(ret);
464 }
465
466 static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject)
467 {
468     jlong ret = init_alarm_driver();
469     if (ret) {
470         return ret;
471     }
472
473     return init_timerfd();
474 }
475
476 static void android_server_AlarmManagerService_close(JNIEnv*, jobject, jlong nativeData)
477 {
478     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
479     delete impl;
480 }
481
482 static void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds)
483 {
484     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
485     struct timespec ts;
486     ts.tv_sec = seconds;
487     ts.tv_nsec = nanoseconds;
488
489     int result = impl->set(type, &ts);
490     if (result < 0)
491     {
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));
495     }
496 }
497
498 static void android_server_AlarmManagerService_clear(JNIEnv*, jobject, jlong nativeData, jint type,
499 jlong seconds, jlong nanoseconds)
500 {
501     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
502     struct timespec ts;
503     ts.tv_sec = seconds;
504     ts.tv_nsec = nanoseconds;
505
506     int result = impl->clear(type, &ts);
507     if (result < 0)
508     {
509         ALOGE("Unable to clear alarm  %lld.%09lld: %s\n",
510               static_cast<long long>(seconds),
511               static_cast<long long>(nanoseconds), strerror(errno));
512     }
513 }
514
515 static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jlong nativeData)
516 {
517     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
518     int result = 0;
519
520     do
521     {
522         result = impl->waitForAlarm();
523     } while (result < 0 && errno == EINTR);
524
525     if (result < 0)
526     {
527         ALOGE("Unable to wait on alarm: %s\n", strerror(errno));
528         return 0;
529     }
530
531     return result;
532 }
533
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},
543 };
544
545 int register_android_server_AlarmManagerService(JNIEnv* env)
546 {
547     return jniRegisterNativeMethods(env, "com/android/server/AlarmManagerService",
548                                     sMethods, NELEM(sMethods));
549 }
550
551 } /* namespace android */