• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 namespace android {
44 
45 static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1;
46 static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = {
47     CLOCK_REALTIME_ALARM,
48     CLOCK_REALTIME,
49     CLOCK_BOOTTIME_ALARM,
50     CLOCK_BOOTTIME,
51     CLOCK_MONOTONIC,
52     CLOCK_REALTIME,
53 };
54 /* to match the legacy alarm driver implementation, we need an extra
55    CLOCK_REALTIME fd which exists specifically to be canceled on RTC changes */
56 
57 class AlarmImpl
58 {
59 public:
60     AlarmImpl(int *fds, size_t n_fds);
61     virtual ~AlarmImpl();
62 
63     virtual int set(int type, struct timespec *ts) = 0;
64     virtual int setTime(struct timeval *tv) = 0;
65     virtual int waitForAlarm() = 0;
66 
67 protected:
68     int *fds;
69     size_t n_fds;
70 };
71 
72 class AlarmImplAlarmDriver : public AlarmImpl
73 {
74 public:
AlarmImplAlarmDriver(int fd)75     AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }
76 
77     int set(int type, struct timespec *ts);
78     int setTime(struct timeval *tv);
79     int waitForAlarm();
80 };
81 
82 class AlarmImplTimerFd : public AlarmImpl
83 {
84 public:
AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS],int epollfd,int rtc_id)85     AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd, int rtc_id) :
86         AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd), rtc_id(rtc_id) { }
87     ~AlarmImplTimerFd();
88 
89     int set(int type, struct timespec *ts);
90     int setTime(struct timeval *tv);
91     int waitForAlarm();
92 
93 private:
94     int epollfd;
95     int rtc_id;
96 };
97 
AlarmImpl(int * fds_,size_t n_fds)98 AlarmImpl::AlarmImpl(int *fds_, size_t n_fds) : fds(new int[n_fds]),
99         n_fds(n_fds)
100 {
101     memcpy(fds, fds_, n_fds * sizeof(fds[0]));
102 }
103 
~AlarmImpl()104 AlarmImpl::~AlarmImpl()
105 {
106     for (size_t i = 0; i < n_fds; i++) {
107         close(fds[i]);
108     }
109     delete [] fds;
110 }
111 
set(int type,struct timespec * ts)112 int AlarmImplAlarmDriver::set(int type, struct timespec *ts)
113 {
114     return ioctl(fds[0], ANDROID_ALARM_SET(type), ts);
115 }
116 
setTime(struct timeval * tv)117 int AlarmImplAlarmDriver::setTime(struct timeval *tv)
118 {
119     struct timespec ts;
120     int res;
121 
122     ts.tv_sec = tv->tv_sec;
123     ts.tv_nsec = tv->tv_usec * 1000;
124     res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts);
125     if (res < 0)
126         ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
127     return res;
128 }
129 
waitForAlarm()130 int AlarmImplAlarmDriver::waitForAlarm()
131 {
132     return ioctl(fds[0], ANDROID_ALARM_WAIT);
133 }
134 
~AlarmImplTimerFd()135 AlarmImplTimerFd::~AlarmImplTimerFd()
136 {
137     for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
138         epoll_ctl(epollfd, EPOLL_CTL_DEL, fds[i], NULL);
139     }
140     close(epollfd);
141 }
142 
set(int type,struct timespec * ts)143 int AlarmImplTimerFd::set(int type, struct timespec *ts)
144 {
145     if (type > ANDROID_ALARM_TYPE_COUNT) {
146         errno = EINVAL;
147         return -1;
148     }
149 
150     if (!ts->tv_nsec && !ts->tv_sec) {
151         ts->tv_nsec = 1;
152     }
153     /* timerfd interprets 0 = disarm, so replace with a practically
154        equivalent deadline of 1 ns */
155 
156     struct itimerspec spec;
157     memset(&spec, 0, sizeof(spec));
158     memcpy(&spec.it_value, ts, sizeof(spec.it_value));
159 
160     return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
161 }
162 
setTime(struct timeval * tv)163 int AlarmImplTimerFd::setTime(struct timeval *tv)
164 {
165     struct rtc_time rtc;
166     struct tm tm, *gmtime_res;
167     int fd;
168     int res;
169 
170     res = settimeofday(tv, NULL);
171     if (res < 0) {
172         ALOGV("settimeofday() failed: %s\n", strerror(errno));
173         return -1;
174     }
175 
176     if (rtc_id < 0) {
177         ALOGV("Not setting RTC because wall clock RTC was not found");
178         errno = ENODEV;
179         return -1;
180     }
181 
182     android::String8 rtc_dev = String8::format("/dev/rtc%d", rtc_id);
183     fd = open(rtc_dev.string(), O_RDWR);
184     if (fd < 0) {
185         ALOGV("Unable to open %s: %s\n", rtc_dev.string(), strerror(errno));
186         return res;
187     }
188 
189     gmtime_res = gmtime_r(&tv->tv_sec, &tm);
190     if (!gmtime_res) {
191         ALOGV("gmtime_r() failed: %s\n", strerror(errno));
192         res = -1;
193         goto done;
194     }
195 
196     memset(&rtc, 0, sizeof(rtc));
197     rtc.tm_sec = tm.tm_sec;
198     rtc.tm_min = tm.tm_min;
199     rtc.tm_hour = tm.tm_hour;
200     rtc.tm_mday = tm.tm_mday;
201     rtc.tm_mon = tm.tm_mon;
202     rtc.tm_year = tm.tm_year;
203     rtc.tm_wday = tm.tm_wday;
204     rtc.tm_yday = tm.tm_yday;
205     rtc.tm_isdst = tm.tm_isdst;
206     res = ioctl(fd, RTC_SET_TIME, &rtc);
207     if (res < 0)
208         ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
209 done:
210     close(fd);
211     return res;
212 }
213 
waitForAlarm()214 int AlarmImplTimerFd::waitForAlarm()
215 {
216     epoll_event events[N_ANDROID_TIMERFDS];
217 
218     int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1);
219     if (nevents < 0) {
220         return nevents;
221     }
222 
223     int result = 0;
224     for (int i = 0; i < nevents; i++) {
225         uint32_t alarm_idx = events[i].data.u32;
226         uint64_t unused;
227         ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused));
228         if (err < 0) {
229             if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) {
230                 result |= ANDROID_ALARM_TIME_CHANGE_MASK;
231             } else {
232                 return err;
233             }
234         } else {
235             result |= (1 << alarm_idx);
236         }
237     }
238 
239     return result;
240 }
241 
android_server_AlarmManagerService_setKernelTime(JNIEnv *,jobject,jlong nativeData,jlong millis)242 static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
243 {
244     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
245     struct timeval tv;
246     int ret;
247 
248     if (millis <= 0 || millis / 1000LL >= INT_MAX) {
249         return -1;
250     }
251 
252     tv.tv_sec = (time_t) (millis / 1000LL);
253     tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
254 
255     ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
256 
257     ret = impl->setTime(&tv);
258 
259     if(ret < 0) {
260         ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
261         ret = -1;
262     }
263     return ret;
264 }
265 
android_server_AlarmManagerService_setKernelTimezone(JNIEnv *,jobject,jlong,jint minswest)266 static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
267 {
268     struct timezone tz;
269 
270     tz.tz_minuteswest = minswest;
271     tz.tz_dsttime = 0;
272 
273     int result = settimeofday(NULL, &tz);
274     if (result < 0) {
275         ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno));
276         return -1;
277     } else {
278         ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest);
279     }
280 
281     return 0;
282 }
283 
init_alarm_driver()284 static jlong init_alarm_driver()
285 {
286     int fd = open("/dev/alarm", O_RDWR);
287     if (fd < 0) {
288         ALOGV("opening alarm driver failed: %s", strerror(errno));
289         return 0;
290     }
291 
292     AlarmImpl *ret = new AlarmImplAlarmDriver(fd);
293     return reinterpret_cast<jlong>(ret);
294 }
295 
296 static const char rtc_sysfs[] = "/sys/class/rtc";
297 
rtc_is_hctosys(unsigned int rtc_id)298 static bool rtc_is_hctosys(unsigned int rtc_id)
299 {
300     android::String8 hctosys_path = String8::format("%s/rtc%u/hctosys",
301             rtc_sysfs, rtc_id);
302 
303     FILE *file = fopen(hctosys_path.string(), "re");
304     if (!file) {
305         ALOGE("failed to open %s: %s", hctosys_path.string(), strerror(errno));
306         return false;
307     }
308 
309     unsigned int hctosys;
310     bool ret = false;
311     int err = fscanf(file, "%u", &hctosys);
312     if (err == EOF)
313         ALOGE("failed to read from %s: %s", hctosys_path.string(),
314                 strerror(errno));
315     else if (err == 0)
316         ALOGE("%s did not have expected contents", hctosys_path.string());
317     else
318         ret = hctosys;
319 
320     fclose(file);
321     return ret;
322 }
323 
wall_clock_rtc()324 static int wall_clock_rtc()
325 {
326     DIR *dir = opendir(rtc_sysfs);
327     if (!dir) {
328         ALOGE("failed to open %s: %s", rtc_sysfs, strerror(errno));
329         return -1;
330     }
331 
332     struct dirent *dirent;
333     while (errno = 0, dirent = readdir(dir)) {
334         unsigned int rtc_id;
335         int matched = sscanf(dirent->d_name, "rtc%u", &rtc_id);
336 
337         if (matched < 0)
338             break;
339         else if (matched != 1)
340             continue;
341 
342         if (rtc_is_hctosys(rtc_id)) {
343             ALOGV("found wall clock RTC %u", rtc_id);
344             return rtc_id;
345         }
346     }
347 
348     if (errno == 0)
349         ALOGW("no wall clock RTC found");
350     else
351         ALOGE("failed to enumerate RTCs: %s", strerror(errno));
352 
353     return -1;
354 }
355 
init_timerfd()356 static jlong init_timerfd()
357 {
358     int epollfd;
359     int fds[N_ANDROID_TIMERFDS];
360 
361     epollfd = epoll_create(N_ANDROID_TIMERFDS);
362     if (epollfd < 0) {
363         ALOGV("epoll_create(%zu) failed: %s", N_ANDROID_TIMERFDS,
364                 strerror(errno));
365         return 0;
366     }
367 
368     for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
369         fds[i] = timerfd_create(android_alarm_to_clockid[i], 0);
370         if (fds[i] < 0) {
371             ALOGV("timerfd_create(%u) failed: %s",  android_alarm_to_clockid[i],
372                     strerror(errno));
373             close(epollfd);
374             for (size_t j = 0; j < i; j++) {
375                 close(fds[j]);
376             }
377             return 0;
378         }
379     }
380 
381     AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd, wall_clock_rtc());
382 
383     for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
384         epoll_event event;
385         event.events = EPOLLIN | EPOLLWAKEUP;
386         event.data.u32 = i;
387 
388         int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event);
389         if (err < 0) {
390             ALOGV("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno));
391             delete ret;
392             return 0;
393         }
394     }
395 
396     struct itimerspec spec;
397     memset(&spec, 0, sizeof(spec));
398     /* 0 = disarmed; the timerfd doesn't need to be armed to get
399        RTC change notifications, just set up as cancelable */
400 
401     int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT],
402             TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL);
403     if (err < 0) {
404         ALOGV("timerfd_settime() failed: %s", strerror(errno));
405         delete ret;
406         return 0;
407     }
408 
409     return reinterpret_cast<jlong>(ret);
410 }
411 
android_server_AlarmManagerService_init(JNIEnv *,jobject)412 static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject)
413 {
414     jlong ret = init_alarm_driver();
415     if (ret) {
416         return ret;
417     }
418 
419     return init_timerfd();
420 }
421 
android_server_AlarmManagerService_close(JNIEnv *,jobject,jlong nativeData)422 static void android_server_AlarmManagerService_close(JNIEnv*, jobject, jlong nativeData)
423 {
424     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
425     delete impl;
426 }
427 
android_server_AlarmManagerService_set(JNIEnv *,jobject,jlong nativeData,jint type,jlong seconds,jlong nanoseconds)428 static void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds)
429 {
430     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
431     struct timespec ts;
432     ts.tv_sec = seconds;
433     ts.tv_nsec = nanoseconds;
434 
435     int result = impl->set(type, &ts);
436     if (result < 0)
437     {
438         ALOGE("Unable to set alarm to %lld.%09lld: %s\n",
439               static_cast<long long>(seconds),
440               static_cast<long long>(nanoseconds), strerror(errno));
441     }
442 }
443 
android_server_AlarmManagerService_waitForAlarm(JNIEnv *,jobject,jlong nativeData)444 static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jlong nativeData)
445 {
446     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
447     int result = 0;
448 
449     do
450     {
451         result = impl->waitForAlarm();
452     } while (result < 0 && errno == EINTR);
453 
454     if (result < 0)
455     {
456         ALOGE("Unable to wait on alarm: %s\n", strerror(errno));
457         return 0;
458     }
459 
460     return result;
461 }
462 
463 static JNINativeMethod sMethods[] = {
464      /* name, signature, funcPtr */
465     {"init", "()J", (void*)android_server_AlarmManagerService_init},
466     {"close", "(J)V", (void*)android_server_AlarmManagerService_close},
467     {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
468     {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
469     {"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},
470     {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
471 };
472 
register_android_server_AlarmManagerService(JNIEnv * env)473 int register_android_server_AlarmManagerService(JNIEnv* env)
474 {
475     return jniRegisterNativeMethods(env, "com/android/server/AlarmManagerService",
476                                     sMethods, NELEM(sMethods));
477 }
478 
479 } /* namespace android */
480