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)79     AlarmImpl(const TimerFds &fds, int epollfd)
80           : fds{fds}, epollfd{epollfd} {}
81     ~AlarmImpl();
82 
83     int set(int type, struct timespec *ts);
84     int waitForAlarm();
85     int getTime(int type, struct itimerspec *spec);
86 
87 private:
88     const TimerFds fds;
89     const int epollfd;
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 
waitForAlarm()132 int AlarmImpl::waitForAlarm()
133 {
134     epoll_event events[N_ANDROID_TIMERFDS];
135 
136     int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1);
137     if (nevents < 0) {
138         return nevents;
139     }
140 
141     int result = 0;
142     for (int i = 0; i < nevents; i++) {
143         uint32_t alarm_idx = events[i].data.u32;
144         uint64_t unused;
145         ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused));
146         // Worth evaluating even if read fails with EAGAIN, since epoll_wait
147         // returned. (see b/78560047#comment34)
148         if (err < 0 && errno != EAGAIN) {
149             if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) {
150                 result |= ANDROID_ALARM_TIME_CHANGE_MASK;
151             } else {
152                 return err;
153             }
154         } else {
155             result |= (1 << alarm_idx);
156         }
157     }
158 
159     return result;
160 }
161 
android_server_alarm_AlarmManagerService_setKernelTimezone(JNIEnv *,jobject,jlong,jint minswest)162 static jint android_server_alarm_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
163 {
164     struct timezone tz;
165 
166     tz.tz_minuteswest = minswest;
167     tz.tz_dsttime = 0;
168 
169     int result = settimeofday(NULL, &tz);
170     if (result < 0) {
171         ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno));
172         return -1;
173     } else {
174         ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest);
175     }
176 
177     return 0;
178 }
179 
log_timerfd_create_error(clockid_t id)180 static void log_timerfd_create_error(clockid_t id)
181 {
182     if (errno == EINVAL) {
183         switch (id) {
184         case CLOCK_REALTIME_ALARM:
185         case CLOCK_BOOTTIME_ALARM:
186             ALOGE("kernel missing required commits:");
187             ALOGE("https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=6cffe00f7d4e24679eae6b7aae4caaf915288256");
188             ALOGE("https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=11ffa9d6065f344a9bd769a2452f26f2f671e5f8");
189             LOG_ALWAYS_FATAL("kernel does not support timerfd_create() with alarm timers");
190             break;
191 
192         case CLOCK_BOOTTIME:
193             ALOGE("kernel missing required commit:");
194             ALOGE("https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=4a2378a943f09907fb1ae35c15de917f60289c14");
195             LOG_ALWAYS_FATAL("kernel does not support timerfd_create(CLOCK_BOOTTIME)");
196             break;
197 
198         default:
199             break;
200         }
201     }
202 
203     ALOGE("timerfd_create(%u) failed: %s", id, strerror(errno));
204 }
205 
android_server_alarm_AlarmManagerService_init(JNIEnv *,jobject)206 static jlong android_server_alarm_AlarmManagerService_init(JNIEnv*, jobject)
207 {
208     int epollfd;
209     TimerFds fds;
210 
211     epollfd = epoll_create(fds.size());
212     if (epollfd < 0) {
213         ALOGE("epoll_create(%zu) failed: %s", fds.size(), strerror(errno));
214         return 0;
215     }
216 
217     for (size_t i = 0; i < fds.size(); i++) {
218         fds[i] = timerfd_create(android_alarm_to_clockid[i], TFD_NONBLOCK);
219         if (fds[i] < 0) {
220             log_timerfd_create_error(android_alarm_to_clockid[i]);
221             close(epollfd);
222             for (size_t j = 0; j < i; j++) {
223                 close(fds[j]);
224             }
225             return 0;
226         }
227     }
228 
229     std::unique_ptr<AlarmImpl> alarm{new AlarmImpl(fds, epollfd)};
230 
231     for (size_t i = 0; i < fds.size(); i++) {
232         epoll_event event;
233         event.events = EPOLLIN | EPOLLWAKEUP;
234         event.data.u32 = i;
235 
236         int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event);
237         if (err < 0) {
238             ALOGE("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno));
239             return 0;
240         }
241     }
242 
243     struct itimerspec spec = {};
244     /* 0 = disarmed; the timerfd doesn't need to be armed to get
245        RTC change notifications, just set up as cancelable */
246 
247     int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT],
248             TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL);
249     if (err < 0) {
250         ALOGE("timerfd_settime() failed: %s", strerror(errno));
251         return 0;
252     }
253 
254     return reinterpret_cast<jlong>(alarm.release());
255 }
256 
android_server_alarm_AlarmManagerService_getNextAlarm(JNIEnv *,jobject,jlong nativeData,jint type)257 static jlong android_server_alarm_AlarmManagerService_getNextAlarm(JNIEnv*, jobject, jlong nativeData, jint type)
258 {
259     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
260     struct itimerspec spec;
261     memset(&spec, 0, sizeof(spec));
262     const int result = impl->getTime(type, &spec);
263     if (result < 0)
264     {
265         ALOGE("timerfd_gettime() failed for fd %d: %s\n", static_cast<int>(type), strerror(errno));
266         return result;
267     }
268     struct timespec nextTimespec = spec.it_value;
269     long long millis = nextTimespec.tv_sec * 1000LL;
270     millis += (nextTimespec.tv_nsec / 1000000LL);
271     return static_cast<jlong>(millis);
272 }
273 
android_server_alarm_AlarmManagerService_close(JNIEnv *,jobject,jlong nativeData)274 static void android_server_alarm_AlarmManagerService_close(JNIEnv*, jobject, jlong nativeData)
275 {
276     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
277     delete impl;
278 }
279 
android_server_alarm_AlarmManagerService_set(JNIEnv *,jobject,jlong nativeData,jint type,jlong seconds,jlong nanoseconds)280 static jint android_server_alarm_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds)
281 {
282     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
283     struct timespec ts;
284     ts.tv_sec = seconds;
285     ts.tv_nsec = nanoseconds;
286 
287     const int result = impl->set(type, &ts);
288     if (result < 0)
289     {
290         ALOGE("Unable to set alarm to %lld.%09lld: %s\n",
291               static_cast<long long>(seconds),
292               static_cast<long long>(nanoseconds), strerror(errno));
293     }
294     return result >= 0 ? 0 : errno;
295 }
296 
android_server_alarm_AlarmManagerService_waitForAlarm(JNIEnv *,jobject,jlong nativeData)297 static jint android_server_alarm_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jlong nativeData)
298 {
299     AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
300     int result = 0;
301 
302     do
303     {
304         result = impl->waitForAlarm();
305     } while (result < 0 && errno == EINTR);
306 
307     if (result < 0)
308     {
309         ALOGE("Unable to wait on alarm: %s\n", strerror(errno));
310         return 0;
311     }
312 
313     return result;
314 }
315 
316 static const JNINativeMethod sMethods[] = {
317      /* name, signature, funcPtr */
318     {"init", "()J", (void*)android_server_alarm_AlarmManagerService_init},
319     {"close", "(J)V", (void*)android_server_alarm_AlarmManagerService_close},
320     {"set", "(JIJJ)I", (void*)android_server_alarm_AlarmManagerService_set},
321     {"waitForAlarm", "(J)I", (void*)android_server_alarm_AlarmManagerService_waitForAlarm},
322     {"setKernelTimezone", "(JI)I", (void*)android_server_alarm_AlarmManagerService_setKernelTimezone},
323     {"getNextAlarm", "(JI)J", (void*)android_server_alarm_AlarmManagerService_getNextAlarm},
324 };
325 
register_android_server_alarm_AlarmManagerService(JNIEnv * env)326 int register_android_server_alarm_AlarmManagerService(JNIEnv* env)
327 {
328     return jniRegisterNativeMethods(env, "com/android/server/alarm/AlarmManagerService",
329                                     sMethods, NELEM(sMethods));
330 }
331 
332 } /* namespace android */
333