1 /*
2 ** Copyright 2006, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 ** http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17 #define LOG_TAG "AlarmManagerService"
18
19 #include <android-base/file.h>
20 #include <android-base/unique_fd.h>
21 #include <nativehelper/JNIHelp.h>
22 #include <utils/Log.h>
23 #include <utils/String8.h>
24 #include <utils/misc.h>
25 #include "jni.h"
26
27 #include <dirent.h>
28 #include <fcntl.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <sys/epoll.h>
32 #include <sys/timerfd.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <arpa/inet.h>
36 #include <netinet/in.h>
37 #include <stdlib.h>
38 #include <errno.h>
39 #include <unistd.h>
40 #include <linux/ioctl.h>
41 #include <linux/rtc.h>
42
43 #include <array>
44 #include <limits>
45 #include <memory>
46
47 namespace android {
48
49 static constexpr int ANDROID_ALARM_TIME_CHANGE_MASK = 1 << 16;
50
51 /**
52 * The AlarmManager alarm constants:
53 *
54 * RTC_WAKEUP
55 * RTC
56 * REALTIME_WAKEUP
57 * REALTIME
58 * SYSTEMTIME (only defined in old alarm driver header, possibly unused?)
59 *
60 * We also need an extra CLOCK_REALTIME fd which exists specifically to be
61 * canceled on RTC changes.
62 */
63 static const size_t ANDROID_ALARM_TYPE_COUNT = 5;
64 static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1;
65 static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = {
66 CLOCK_REALTIME_ALARM,
67 CLOCK_REALTIME,
68 CLOCK_BOOTTIME_ALARM,
69 CLOCK_BOOTTIME,
70 CLOCK_MONOTONIC,
71 CLOCK_REALTIME,
72 };
73
74 typedef std::array<int, N_ANDROID_TIMERFDS> TimerFds;
75
76 class AlarmImpl
77 {
78 public:
AlarmImpl(const TimerFds & fds,int epollfd,const std::string & rtc_dev)79 AlarmImpl(const TimerFds &fds, int epollfd, const std::string &rtc_dev)
80 : fds{fds}, epollfd{epollfd}, rtc_dev{rtc_dev} {}
81 ~AlarmImpl();
82
83 int set(int type, struct timespec *ts);
84 int setTime(struct timeval *tv);
85 int waitForAlarm();
86 int getTime(int type, struct itimerspec *spec);
87
88 private:
89 const TimerFds fds;
90 const int epollfd;
91 std::string rtc_dev;
92 };
93
~AlarmImpl()94 AlarmImpl::~AlarmImpl()
95 {
96 for (auto fd : fds) {
97 epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, nullptr);
98 close(fd);
99 }
100
101 close(epollfd);
102 }
103
set(int type,struct timespec * ts)104 int AlarmImpl::set(int type, struct timespec *ts)
105 {
106 if (static_cast<size_t>(type) > ANDROID_ALARM_TYPE_COUNT) {
107 errno = EINVAL;
108 return -1;
109 }
110
111 if (!ts->tv_nsec && !ts->tv_sec) {
112 ts->tv_nsec = 1;
113 }
114 /* timerfd interprets 0 = disarm, so replace with a practically
115 equivalent deadline of 1 ns */
116
117 struct itimerspec spec;
118 memset(&spec, 0, sizeof(spec));
119 memcpy(&spec.it_value, ts, sizeof(spec.it_value));
120
121 return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
122 }
123
getTime(int type,struct itimerspec * spec)124 int AlarmImpl::getTime(int type, struct itimerspec *spec)
125 {
126 if (static_cast<size_t>(type) > ANDROID_ALARM_TYPE_COUNT) {
127 errno = EINVAL;
128 return -1;
129 }
130
131 return timerfd_gettime(fds[type], spec);
132 }
133
setTime(struct timeval * tv)134 int AlarmImpl::setTime(struct timeval *tv)
135 {
136 if (settimeofday(tv, NULL) == -1) {
137 ALOGV("settimeofday() failed: %s", strerror(errno));
138 return -1;
139 }
140
141 android::base::unique_fd fd{open(rtc_dev.c_str(), O_RDWR)};
142 if (!fd.ok()) {
143 ALOGE("Unable to open %s: %s", rtc_dev.c_str(), strerror(errno));
144 return -1;
145 }
146
147 struct tm tm;
148 if (!gmtime_r(&tv->tv_sec, &tm)) {
149 ALOGV("gmtime_r() failed: %s", strerror(errno));
150 return -1;
151 }
152
153 struct rtc_time rtc = {};
154 rtc.tm_sec = tm.tm_sec;
155 rtc.tm_min = tm.tm_min;
156 rtc.tm_hour = tm.tm_hour;
157 rtc.tm_mday = tm.tm_mday;
158 rtc.tm_mon = tm.tm_mon;
159 rtc.tm_year = tm.tm_year;
160 rtc.tm_wday = tm.tm_wday;
161 rtc.tm_yday = tm.tm_yday;
162 rtc.tm_isdst = tm.tm_isdst;
163 if (ioctl(fd, RTC_SET_TIME, &rtc) == -1) {
164 ALOGV("RTC_SET_TIME ioctl failed: %s", strerror(errno));
165 return -1;
166 }
167
168 return 0;
169 }
170
waitForAlarm()171 int AlarmImpl::waitForAlarm()
172 {
173 epoll_event events[N_ANDROID_TIMERFDS];
174
175 int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1);
176 if (nevents < 0) {
177 return nevents;
178 }
179
180 int result = 0;
181 for (int i = 0; i < nevents; i++) {
182 uint32_t alarm_idx = events[i].data.u32;
183 uint64_t unused;
184 ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused));
185 // Worth evaluating even if read fails with EAGAIN, since epoll_wait
186 // returned. (see b/78560047#comment34)
187 if (err < 0 && errno != EAGAIN) {
188 if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) {
189 result |= ANDROID_ALARM_TIME_CHANGE_MASK;
190 } else {
191 return err;
192 }
193 } else {
194 result |= (1 << alarm_idx);
195 }
196 }
197
198 return result;
199 }
200
android_server_alarm_AlarmManagerService_setKernelTime(JNIEnv *,jobject,jlong nativeData,jlong millis)201 static jint android_server_alarm_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
202 {
203 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
204
205 if (millis <= 0 || millis / 1000LL >= std::numeric_limits<time_t>::max()) {
206 return -1;
207 }
208
209 struct timeval tv;
210 tv.tv_sec = (millis / 1000LL);
211 tv.tv_usec = ((millis % 1000LL) * 1000LL);
212
213 ALOGD("Setting time of day to sec=%ld", tv.tv_sec);
214
215 int ret = impl->setTime(&tv);
216 if (ret < 0) {
217 ALOGW("Unable to set rtc to %ld: %s", tv.tv_sec, strerror(errno));
218 ret = -1;
219 }
220 return ret;
221 }
222
android_server_alarm_AlarmManagerService_setKernelTimezone(JNIEnv *,jobject,jlong,jint minswest)223 static jint android_server_alarm_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
224 {
225 struct timezone tz;
226
227 tz.tz_minuteswest = minswest;
228 tz.tz_dsttime = 0;
229
230 int result = settimeofday(NULL, &tz);
231 if (result < 0) {
232 ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno));
233 return -1;
234 } else {
235 ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest);
236 }
237
238 return 0;
239 }
240
log_timerfd_create_error(clockid_t id)241 static void log_timerfd_create_error(clockid_t id)
242 {
243 if (errno == EINVAL) {
244 switch (id) {
245 case CLOCK_REALTIME_ALARM:
246 case CLOCK_BOOTTIME_ALARM:
247 ALOGE("kernel missing required commits:");
248 ALOGE("https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=6cffe00f7d4e24679eae6b7aae4caaf915288256");
249 ALOGE("https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=11ffa9d6065f344a9bd769a2452f26f2f671e5f8");
250 LOG_ALWAYS_FATAL("kernel does not support timerfd_create() with alarm timers");
251 break;
252
253 case CLOCK_BOOTTIME:
254 ALOGE("kernel missing required commit:");
255 ALOGE("https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=4a2378a943f09907fb1ae35c15de917f60289c14");
256 LOG_ALWAYS_FATAL("kernel does not support timerfd_create(CLOCK_BOOTTIME)");
257 break;
258
259 default:
260 break;
261 }
262 }
263
264 ALOGE("timerfd_create(%u) failed: %s", id, strerror(errno));
265 }
266
android_server_alarm_AlarmManagerService_init(JNIEnv *,jobject)267 static jlong android_server_alarm_AlarmManagerService_init(JNIEnv*, jobject)
268 {
269 int epollfd;
270 TimerFds fds;
271
272 epollfd = epoll_create(fds.size());
273 if (epollfd < 0) {
274 ALOGE("epoll_create(%zu) failed: %s", fds.size(), strerror(errno));
275 return 0;
276 }
277
278 for (size_t i = 0; i < fds.size(); i++) {
279 fds[i] = timerfd_create(android_alarm_to_clockid[i], TFD_NONBLOCK);
280 if (fds[i] < 0) {
281 log_timerfd_create_error(android_alarm_to_clockid[i]);
282 close(epollfd);
283 for (size_t j = 0; j < i; j++) {
284 close(fds[j]);
285 }
286 return 0;
287 }
288 }
289
290 // Find the wall clock RTC. We expect this always to be /dev/rtc0, but
291 // check the /dev/rtc symlink first so that legacy devices that don't use
292 // rtc0 can add a symlink rather than need to carry a local patch to this
293 // code.
294 //
295 // TODO: if you're reading this in a world where all devices are using the
296 // GKI, you can remove the readlink and just assume /dev/rtc0.
297 std::string dev_rtc;
298 if (!android::base::Readlink("/dev/rtc", &dev_rtc)) {
299 dev_rtc = "/dev/rtc0";
300 }
301
302 std::unique_ptr<AlarmImpl> alarm{new AlarmImpl(fds, epollfd, dev_rtc)};
303
304 for (size_t i = 0; i < fds.size(); i++) {
305 epoll_event event;
306 event.events = EPOLLIN | EPOLLWAKEUP;
307 event.data.u32 = i;
308
309 int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event);
310 if (err < 0) {
311 ALOGE("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno));
312 return 0;
313 }
314 }
315
316 struct itimerspec spec = {};
317 /* 0 = disarmed; the timerfd doesn't need to be armed to get
318 RTC change notifications, just set up as cancelable */
319
320 int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT],
321 TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL);
322 if (err < 0) {
323 ALOGE("timerfd_settime() failed: %s", strerror(errno));
324 return 0;
325 }
326
327 return reinterpret_cast<jlong>(alarm.release());
328 }
329
android_server_alarm_AlarmManagerService_getNextAlarm(JNIEnv *,jobject,jlong nativeData,jint type)330 static jlong android_server_alarm_AlarmManagerService_getNextAlarm(JNIEnv*, jobject, jlong nativeData, jint type)
331 {
332 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
333 struct itimerspec spec;
334 memset(&spec, 0, sizeof(spec));
335 const int result = impl->getTime(type, &spec);
336 if (result < 0)
337 {
338 ALOGE("timerfd_gettime() failed for fd %d: %s\n", static_cast<int>(type), strerror(errno));
339 return result;
340 }
341 struct timespec nextTimespec = spec.it_value;
342 long long millis = nextTimespec.tv_sec * 1000LL;
343 millis += (nextTimespec.tv_nsec / 1000000LL);
344 return static_cast<jlong>(millis);
345 }
346
android_server_alarm_AlarmManagerService_close(JNIEnv *,jobject,jlong nativeData)347 static void android_server_alarm_AlarmManagerService_close(JNIEnv*, jobject, jlong nativeData)
348 {
349 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
350 delete impl;
351 }
352
android_server_alarm_AlarmManagerService_set(JNIEnv *,jobject,jlong nativeData,jint type,jlong seconds,jlong nanoseconds)353 static jint android_server_alarm_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds)
354 {
355 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
356 struct timespec ts;
357 ts.tv_sec = seconds;
358 ts.tv_nsec = nanoseconds;
359
360 const int result = impl->set(type, &ts);
361 if (result < 0)
362 {
363 ALOGE("Unable to set alarm to %lld.%09lld: %s\n",
364 static_cast<long long>(seconds),
365 static_cast<long long>(nanoseconds), strerror(errno));
366 }
367 return result >= 0 ? 0 : errno;
368 }
369
android_server_alarm_AlarmManagerService_waitForAlarm(JNIEnv *,jobject,jlong nativeData)370 static jint android_server_alarm_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jlong nativeData)
371 {
372 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
373 int result = 0;
374
375 do
376 {
377 result = impl->waitForAlarm();
378 } while (result < 0 && errno == EINTR);
379
380 if (result < 0)
381 {
382 ALOGE("Unable to wait on alarm: %s\n", strerror(errno));
383 return 0;
384 }
385
386 return result;
387 }
388
389 static const JNINativeMethod sMethods[] = {
390 /* name, signature, funcPtr */
391 {"init", "()J", (void*)android_server_alarm_AlarmManagerService_init},
392 {"close", "(J)V", (void*)android_server_alarm_AlarmManagerService_close},
393 {"set", "(JIJJ)I", (void*)android_server_alarm_AlarmManagerService_set},
394 {"waitForAlarm", "(J)I", (void*)android_server_alarm_AlarmManagerService_waitForAlarm},
395 {"setKernelTime", "(JJ)I", (void*)android_server_alarm_AlarmManagerService_setKernelTime},
396 {"setKernelTimezone", "(JI)I", (void*)android_server_alarm_AlarmManagerService_setKernelTimezone},
397 {"getNextAlarm", "(JI)J", (void*)android_server_alarm_AlarmManagerService_getNextAlarm},
398 };
399
register_android_server_alarm_AlarmManagerService(JNIEnv * env)400 int register_android_server_alarm_AlarmManagerService(JNIEnv* env)
401 {
402 return jniRegisterNativeMethods(env, "com/android/server/alarm/AlarmManagerService",
403 sMethods, NELEM(sMethods));
404 }
405
406 } /* namespace android */
407