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