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