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