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