• Home
  • History
  • Annotate
  • 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 
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 
41 namespace android {
42 
43 static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1;
44 static 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 
55 class AlarmImpl
56 {
57 public:
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 
65 protected:
66     int *fds;
67     size_t n_fds;
68 };
69 
70 class AlarmImplAlarmDriver : public AlarmImpl
71 {
72 public:
AlarmImplAlarmDriver(int fd)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 
80 class AlarmImplTimerFd : public AlarmImpl
81 {
82 public:
AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS],int epollfd)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 
91 private:
92     int epollfd;
93 };
94 
AlarmImpl(int * fds_,size_t n_fds)95 AlarmImpl::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 
~AlarmImpl()101 AlarmImpl::~AlarmImpl()
102 {
103     for (size_t i = 0; i < n_fds; i++) {
104         close(fds[i]);
105     }
106     delete [] fds;
107 }
108 
set(int type,struct timespec * ts)109 int AlarmImplAlarmDriver::set(int type, struct timespec *ts)
110 {
111     return ioctl(fds[0], ANDROID_ALARM_SET(type), ts);
112 }
113 
setTime(struct timeval * tv)114 int 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 
waitForAlarm()127 int AlarmImplAlarmDriver::waitForAlarm()
128 {
129     return ioctl(fds[0], ANDROID_ALARM_WAIT);
130 }
131 
~AlarmImplTimerFd()132 AlarmImplTimerFd::~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 
set(int type,struct timespec * ts)140 int 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 
setTime(struct timeval * tv)160 int 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));
199 done:
200     close(fd);
201     return res;
202 }
203 
waitForAlarm()204 int 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 
android_server_AlarmManagerService_setKernelTime(JNIEnv *,jobject,jlong nativeData,jlong millis)232 static 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 
android_server_AlarmManagerService_setKernelTimezone(JNIEnv *,jobject,jlong,jint minswest)256 static 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 
init_alarm_driver()274 static 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 
init_timerfd()286 static 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 
android_server_AlarmManagerService_init(JNIEnv *,jobject)342 static 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 
android_server_AlarmManagerService_close(JNIEnv *,jobject,jlong nativeData)352 static void android_server_AlarmManagerService_close(JNIEnv*, jobject, jlong nativeData)
353 {
354     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
355     delete impl;
356 }
357 
android_server_AlarmManagerService_set(JNIEnv *,jobject,jlong nativeData,jint type,jlong seconds,jlong nanoseconds)358 static 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 
android_server_AlarmManagerService_waitForAlarm(JNIEnv *,jobject,jlong nativeData)374 static 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 
393 static 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 
register_android_server_AlarmManagerService(JNIEnv * env)403 int 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