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