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
25#include <fcntl.h>
26#include <stdio.h>
27#include <string.h>
28#include <sys/epoll.h>
29#include <sys/timerfd.h>
30#include <sys/types.h>
31#include <sys/socket.h>
32#include <arpa/inet.h>
33#include <netinet/in.h>
34#include <stdlib.h>
35#include <errno.h>
36#include <unistd.h>
37#include <linux/ioctl.h>
38#include <linux/android_alarm.h>
39#include <linux/rtc.h>
40
41namespace android {
42
43static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1;
44static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = {
45    CLOCK_REALTIME_ALARM,
46    CLOCK_REALTIME,
47    CLOCK_BOOTTIME_ALARM,
48    CLOCK_BOOTTIME,
49    CLOCK_MONOTONIC,
50    CLOCK_REALTIME,
51};
52/* to match the legacy alarm driver implementation, we need an extra
53   CLOCK_REALTIME fd which exists specifically to be canceled on RTC changes */
54
55class AlarmImpl
56{
57public:
58    AlarmImpl(int *fds, size_t n_fds);
59    virtual ~AlarmImpl();
60
61    virtual int set(int type, struct timespec *ts) = 0;
62    virtual int setTime(struct timeval *tv) = 0;
63    virtual int waitForAlarm() = 0;
64
65protected:
66    int *fds;
67    size_t n_fds;
68};
69
70class AlarmImplAlarmDriver : public AlarmImpl
71{
72public:
73    AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }
74
75    int set(int type, struct timespec *ts);
76    int setTime(struct timeval *tv);
77    int waitForAlarm();
78};
79
80class AlarmImplTimerFd : public AlarmImpl
81{
82public:
83    AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd) :
84        AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd) { }
85    ~AlarmImplTimerFd();
86
87    int set(int type, struct timespec *ts);
88    int setTime(struct timeval *tv);
89    int waitForAlarm();
90
91private:
92    int epollfd;
93};
94
95AlarmImpl::AlarmImpl(int *fds_, size_t n_fds) : fds(new int[n_fds]),
96        n_fds(n_fds)
97{
98    memcpy(fds, fds_, n_fds * sizeof(fds[0]));
99}
100
101AlarmImpl::~AlarmImpl()
102{
103    for (size_t i = 0; i < n_fds; i++) {
104        close(fds[i]);
105    }
106    delete [] fds;
107}
108
109int AlarmImplAlarmDriver::set(int type, struct timespec *ts)
110{
111    return ioctl(fds[0], ANDROID_ALARM_SET(type), ts);
112}
113
114int AlarmImplAlarmDriver::setTime(struct timeval *tv)
115{
116    struct timespec ts;
117    int res;
118
119    ts.tv_sec = tv->tv_sec;
120    ts.tv_nsec = tv->tv_usec * 1000;
121    res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts);
122    if (res < 0)
123        ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
124    return res;
125}
126
127int AlarmImplAlarmDriver::waitForAlarm()
128{
129    return ioctl(fds[0], ANDROID_ALARM_WAIT);
130}
131
132AlarmImplTimerFd::~AlarmImplTimerFd()
133{
134    for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
135        epoll_ctl(epollfd, EPOLL_CTL_DEL, fds[i], NULL);
136    }
137    close(epollfd);
138}
139
140int AlarmImplTimerFd::set(int type, struct timespec *ts)
141{
142    if (type > ANDROID_ALARM_TYPE_COUNT) {
143        errno = EINVAL;
144        return -1;
145    }
146
147    if (!ts->tv_nsec && !ts->tv_sec) {
148        ts->tv_nsec = 1;
149    }
150    /* timerfd interprets 0 = disarm, so replace with a practically
151       equivalent deadline of 1 ns */
152
153    struct itimerspec spec;
154    memset(&spec, 0, sizeof(spec));
155    memcpy(&spec.it_value, ts, sizeof(spec.it_value));
156
157    return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
158}
159
160int AlarmImplTimerFd::setTime(struct timeval *tv)
161{
162    struct rtc_time rtc;
163    struct tm tm, *gmtime_res;
164    int fd;
165    int res;
166
167    res = settimeofday(tv, NULL);
168    if (res < 0) {
169        ALOGV("settimeofday() failed: %s\n", strerror(errno));
170        return -1;
171    }
172
173    fd = open("/dev/rtc0", O_RDWR);
174    if (fd < 0) {
175        ALOGV("Unable to open RTC driver: %s\n", strerror(errno));
176        return res;
177    }
178
179    gmtime_res = gmtime_r(&tv->tv_sec, &tm);
180    if (!gmtime_res) {
181        ALOGV("gmtime_r() failed: %s\n", strerror(errno));
182        res = -1;
183        goto done;
184    }
185
186    memset(&rtc, 0, sizeof(rtc));
187    rtc.tm_sec = tm.tm_sec;
188    rtc.tm_min = tm.tm_min;
189    rtc.tm_hour = tm.tm_hour;
190    rtc.tm_mday = tm.tm_mday;
191    rtc.tm_mon = tm.tm_mon;
192    rtc.tm_year = tm.tm_year;
193    rtc.tm_wday = tm.tm_wday;
194    rtc.tm_yday = tm.tm_yday;
195    rtc.tm_isdst = tm.tm_isdst;
196    res = ioctl(fd, RTC_SET_TIME, &rtc);
197    if (res < 0)
198        ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
199done:
200    close(fd);
201    return res;
202}
203
204int AlarmImplTimerFd::waitForAlarm()
205{
206    epoll_event events[N_ANDROID_TIMERFDS];
207
208    int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1);
209    if (nevents < 0) {
210        return nevents;
211    }
212
213    int result = 0;
214    for (int i = 0; i < nevents; i++) {
215        uint32_t alarm_idx = events[i].data.u32;
216        uint64_t unused;
217        ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused));
218        if (err < 0) {
219            if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) {
220                result |= ANDROID_ALARM_TIME_CHANGE_MASK;
221            } else {
222                return err;
223            }
224        } else {
225            result |= (1 << alarm_idx);
226        }
227    }
228
229    return result;
230}
231
232static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
233{
234    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
235    struct timeval tv;
236    int ret;
237
238    if (millis <= 0 || millis / 1000LL >= INT_MAX) {
239        return -1;
240    }
241
242    tv.tv_sec = (time_t) (millis / 1000LL);
243    tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
244
245    ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
246
247    ret = impl->setTime(&tv);
248
249    if(ret < 0) {
250        ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
251        ret = -1;
252    }
253    return ret;
254}
255
256static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
257{
258    struct timezone tz;
259
260    tz.tz_minuteswest = minswest;
261    tz.tz_dsttime = 0;
262
263    int result = settimeofday(NULL, &tz);
264    if (result < 0) {
265        ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno));
266        return -1;
267    } else {
268        ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest);
269    }
270
271    return 0;
272}
273
274static jlong init_alarm_driver()
275{
276    int fd = open("/dev/alarm", O_RDWR);
277    if (fd < 0) {
278        ALOGV("opening alarm driver failed: %s", strerror(errno));
279        return 0;
280    }
281
282    AlarmImpl *ret = new AlarmImplAlarmDriver(fd);
283    return reinterpret_cast<jlong>(ret);
284}
285
286static jlong init_timerfd()
287{
288    int epollfd;
289    int fds[N_ANDROID_TIMERFDS];
290
291    epollfd = epoll_create(N_ANDROID_TIMERFDS);
292    if (epollfd < 0) {
293        ALOGV("epoll_create(%u) failed: %s", N_ANDROID_TIMERFDS,
294                strerror(errno));
295        return 0;
296    }
297
298    for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
299        fds[i] = timerfd_create(android_alarm_to_clockid[i], 0);
300        if (fds[i] < 0) {
301            ALOGV("timerfd_create(%u) failed: %s",  android_alarm_to_clockid[i],
302                    strerror(errno));
303            close(epollfd);
304            for (size_t j = 0; j < i; j++) {
305                close(fds[j]);
306            }
307            return 0;
308        }
309    }
310
311    AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd);
312
313    for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
314        epoll_event event;
315        event.events = EPOLLIN | EPOLLWAKEUP;
316        event.data.u32 = i;
317
318        int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event);
319        if (err < 0) {
320            ALOGV("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno));
321            delete ret;
322            return 0;
323        }
324    }
325
326    struct itimerspec spec;
327    memset(&spec, 0, sizeof(spec));
328    /* 0 = disarmed; the timerfd doesn't need to be armed to get
329       RTC change notifications, just set up as cancelable */
330
331    int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT],
332            TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL);
333    if (err < 0) {
334        ALOGV("timerfd_settime() failed: %s", strerror(errno));
335        delete ret;
336        return 0;
337    }
338
339    return reinterpret_cast<jlong>(ret);
340}
341
342static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject)
343{
344    jlong ret = init_alarm_driver();
345    if (ret) {
346        return ret;
347    }
348
349    return init_timerfd();
350}
351
352static void android_server_AlarmManagerService_close(JNIEnv*, jobject, jlong nativeData)
353{
354    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
355    delete impl;
356}
357
358static void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds)
359{
360    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
361    struct timespec ts;
362    ts.tv_sec = seconds;
363    ts.tv_nsec = nanoseconds;
364
365    int result = impl->set(type, &ts);
366    if (result < 0)
367    {
368        ALOGE("Unable to set alarm to %lld.%09lld: %s\n",
369              static_cast<long long>(seconds),
370              static_cast<long long>(nanoseconds), strerror(errno));
371    }
372}
373
374static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jlong nativeData)
375{
376    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
377    int result = 0;
378
379    do
380    {
381        result = impl->waitForAlarm();
382    } while (result < 0 && errno == EINTR);
383
384    if (result < 0)
385    {
386        ALOGE("Unable to wait on alarm: %s\n", strerror(errno));
387        return 0;
388    }
389
390    return result;
391}
392
393static JNINativeMethod sMethods[] = {
394     /* name, signature, funcPtr */
395    {"init", "()J", (void*)android_server_AlarmManagerService_init},
396    {"close", "(J)V", (void*)android_server_AlarmManagerService_close},
397    {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
398    {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
399    {"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},
400    {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
401};
402
403int register_android_server_AlarmManagerService(JNIEnv* env)
404{
405    return jniRegisterNativeMethods(env, "com/android/server/AlarmManagerService",
406                                    sMethods, NELEM(sMethods));
407}
408
409} /* namespace android */
410