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 "JNIHelp.h" 21#include "jni.h" 22#include <utils/Log.h> 23#include <utils/misc.h> 24 25#include <fcntl.h> 26#include <stdio.h> 27#include <string.h> 28#include <sys/epoll.h> 29#include <sys/timerfd.h> 30#include <sys/types.h> 31#include <sys/socket.h> 32#include <arpa/inet.h> 33#include <netinet/in.h> 34#include <stdlib.h> 35#include <errno.h> 36#include <unistd.h> 37#include <linux/ioctl.h> 38#include <linux/android_alarm.h> 39#include <linux/rtc.h> 40 41namespace android { 42 43static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1; 44static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = { 45 CLOCK_REALTIME_ALARM, 46 CLOCK_REALTIME, 47 CLOCK_BOOTTIME_ALARM, 48 CLOCK_BOOTTIME, 49 CLOCK_MONOTONIC, 50 CLOCK_REALTIME, 51}; 52/* to match the legacy alarm driver implementation, we need an extra 53 CLOCK_REALTIME fd which exists specifically to be canceled on RTC changes */ 54 55class AlarmImpl 56{ 57public: 58 AlarmImpl(int *fds, size_t n_fds); 59 virtual ~AlarmImpl(); 60 61 virtual int set(int type, struct timespec *ts) = 0; 62 virtual int setTime(struct timeval *tv) = 0; 63 virtual int waitForAlarm() = 0; 64 65protected: 66 int *fds; 67 size_t n_fds; 68}; 69 70class AlarmImplAlarmDriver : public AlarmImpl 71{ 72public: 73 AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { } 74 75 int set(int type, struct timespec *ts); 76 int setTime(struct timeval *tv); 77 int waitForAlarm(); 78}; 79 80class AlarmImplTimerFd : public AlarmImpl 81{ 82public: 83 AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd) : 84 AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd) { } 85 ~AlarmImplTimerFd(); 86 87 int set(int type, struct timespec *ts); 88 int setTime(struct timeval *tv); 89 int waitForAlarm(); 90 91private: 92 int epollfd; 93}; 94 95AlarmImpl::AlarmImpl(int *fds_, size_t n_fds) : fds(new int[n_fds]), 96 n_fds(n_fds) 97{ 98 memcpy(fds, fds_, n_fds * sizeof(fds[0])); 99} 100 101AlarmImpl::~AlarmImpl() 102{ 103 for (size_t i = 0; i < n_fds; i++) { 104 close(fds[i]); 105 } 106 delete [] fds; 107} 108 109int AlarmImplAlarmDriver::set(int type, struct timespec *ts) 110{ 111 return ioctl(fds[0], ANDROID_ALARM_SET(type), ts); 112} 113 114int AlarmImplAlarmDriver::setTime(struct timeval *tv) 115{ 116 struct timespec ts; 117 int res; 118 119 ts.tv_sec = tv->tv_sec; 120 ts.tv_nsec = tv->tv_usec * 1000; 121 res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts); 122 if (res < 0) 123 ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno)); 124 return res; 125} 126 127int AlarmImplAlarmDriver::waitForAlarm() 128{ 129 return ioctl(fds[0], ANDROID_ALARM_WAIT); 130} 131 132AlarmImplTimerFd::~AlarmImplTimerFd() 133{ 134 for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { 135 epoll_ctl(epollfd, EPOLL_CTL_DEL, fds[i], NULL); 136 } 137 close(epollfd); 138} 139 140int AlarmImplTimerFd::set(int type, struct timespec *ts) 141{ 142 if (type > ANDROID_ALARM_TYPE_COUNT) { 143 errno = EINVAL; 144 return -1; 145 } 146 147 if (!ts->tv_nsec && !ts->tv_sec) { 148 ts->tv_nsec = 1; 149 } 150 /* timerfd interprets 0 = disarm, so replace with a practically 151 equivalent deadline of 1 ns */ 152 153 struct itimerspec spec; 154 memset(&spec, 0, sizeof(spec)); 155 memcpy(&spec.it_value, ts, sizeof(spec.it_value)); 156 157 return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL); 158} 159 160int AlarmImplTimerFd::setTime(struct timeval *tv) 161{ 162 struct rtc_time rtc; 163 struct tm tm, *gmtime_res; 164 int fd; 165 int res; 166 167 res = settimeofday(tv, NULL); 168 if (res < 0) { 169 ALOGV("settimeofday() failed: %s\n", strerror(errno)); 170 return -1; 171 } 172 173 fd = open("/dev/rtc0", O_RDWR); 174 if (fd < 0) { 175 ALOGV("Unable to open RTC driver: %s\n", strerror(errno)); 176 return res; 177 } 178 179 gmtime_res = gmtime_r(&tv->tv_sec, &tm); 180 if (!gmtime_res) { 181 ALOGV("gmtime_r() failed: %s\n", strerror(errno)); 182 res = -1; 183 goto done; 184 } 185 186 memset(&rtc, 0, sizeof(rtc)); 187 rtc.tm_sec = tm.tm_sec; 188 rtc.tm_min = tm.tm_min; 189 rtc.tm_hour = tm.tm_hour; 190 rtc.tm_mday = tm.tm_mday; 191 rtc.tm_mon = tm.tm_mon; 192 rtc.tm_year = tm.tm_year; 193 rtc.tm_wday = tm.tm_wday; 194 rtc.tm_yday = tm.tm_yday; 195 rtc.tm_isdst = tm.tm_isdst; 196 res = ioctl(fd, RTC_SET_TIME, &rtc); 197 if (res < 0) 198 ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno)); 199done: 200 close(fd); 201 return res; 202} 203 204int AlarmImplTimerFd::waitForAlarm() 205{ 206 epoll_event events[N_ANDROID_TIMERFDS]; 207 208 int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1); 209 if (nevents < 0) { 210 return nevents; 211 } 212 213 int result = 0; 214 for (int i = 0; i < nevents; i++) { 215 uint32_t alarm_idx = events[i].data.u32; 216 uint64_t unused; 217 ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused)); 218 if (err < 0) { 219 if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) { 220 result |= ANDROID_ALARM_TIME_CHANGE_MASK; 221 } else { 222 return err; 223 } 224 } else { 225 result |= (1 << alarm_idx); 226 } 227 } 228 229 return result; 230} 231 232static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis) 233{ 234 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); 235 struct timeval tv; 236 int ret; 237 238 if (millis <= 0 || millis / 1000LL >= INT_MAX) { 239 return -1; 240 } 241 242 tv.tv_sec = (time_t) (millis / 1000LL); 243 tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL); 244 245 ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec); 246 247 ret = impl->setTime(&tv); 248 249 if(ret < 0) { 250 ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno)); 251 ret = -1; 252 } 253 return ret; 254} 255 256static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest) 257{ 258 struct timezone tz; 259 260 tz.tz_minuteswest = minswest; 261 tz.tz_dsttime = 0; 262 263 int result = settimeofday(NULL, &tz); 264 if (result < 0) { 265 ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno)); 266 return -1; 267 } else { 268 ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest); 269 } 270 271 return 0; 272} 273 274static jlong init_alarm_driver() 275{ 276 int fd = open("/dev/alarm", O_RDWR); 277 if (fd < 0) { 278 ALOGV("opening alarm driver failed: %s", strerror(errno)); 279 return 0; 280 } 281 282 AlarmImpl *ret = new AlarmImplAlarmDriver(fd); 283 return reinterpret_cast<jlong>(ret); 284} 285 286static jlong init_timerfd() 287{ 288 int epollfd; 289 int fds[N_ANDROID_TIMERFDS]; 290 291 epollfd = epoll_create(N_ANDROID_TIMERFDS); 292 if (epollfd < 0) { 293 ALOGV("epoll_create(%u) failed: %s", N_ANDROID_TIMERFDS, 294 strerror(errno)); 295 return 0; 296 } 297 298 for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { 299 fds[i] = timerfd_create(android_alarm_to_clockid[i], 0); 300 if (fds[i] < 0) { 301 ALOGV("timerfd_create(%u) failed: %s", android_alarm_to_clockid[i], 302 strerror(errno)); 303 close(epollfd); 304 for (size_t j = 0; j < i; j++) { 305 close(fds[j]); 306 } 307 return 0; 308 } 309 } 310 311 AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd); 312 313 for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { 314 epoll_event event; 315 event.events = EPOLLIN | EPOLLWAKEUP; 316 event.data.u32 = i; 317 318 int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event); 319 if (err < 0) { 320 ALOGV("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno)); 321 delete ret; 322 return 0; 323 } 324 } 325 326 struct itimerspec spec; 327 memset(&spec, 0, sizeof(spec)); 328 /* 0 = disarmed; the timerfd doesn't need to be armed to get 329 RTC change notifications, just set up as cancelable */ 330 331 int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT], 332 TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL); 333 if (err < 0) { 334 ALOGV("timerfd_settime() failed: %s", strerror(errno)); 335 delete ret; 336 return 0; 337 } 338 339 return reinterpret_cast<jlong>(ret); 340} 341 342static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject) 343{ 344 jlong ret = init_alarm_driver(); 345 if (ret) { 346 return ret; 347 } 348 349 return init_timerfd(); 350} 351 352static void android_server_AlarmManagerService_close(JNIEnv*, jobject, jlong nativeData) 353{ 354 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); 355 delete impl; 356} 357 358static void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds) 359{ 360 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); 361 struct timespec ts; 362 ts.tv_sec = seconds; 363 ts.tv_nsec = nanoseconds; 364 365 int result = impl->set(type, &ts); 366 if (result < 0) 367 { 368 ALOGE("Unable to set alarm to %lld.%09lld: %s\n", 369 static_cast<long long>(seconds), 370 static_cast<long long>(nanoseconds), strerror(errno)); 371 } 372} 373 374static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jlong nativeData) 375{ 376 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); 377 int result = 0; 378 379 do 380 { 381 result = impl->waitForAlarm(); 382 } while (result < 0 && errno == EINTR); 383 384 if (result < 0) 385 { 386 ALOGE("Unable to wait on alarm: %s\n", strerror(errno)); 387 return 0; 388 } 389 390 return result; 391} 392 393static JNINativeMethod sMethods[] = { 394 /* name, signature, funcPtr */ 395 {"init", "()J", (void*)android_server_AlarmManagerService_init}, 396 {"close", "(J)V", (void*)android_server_AlarmManagerService_close}, 397 {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set}, 398 {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm}, 399 {"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime}, 400 {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone}, 401}; 402 403int register_android_server_AlarmManagerService(JNIEnv* env) 404{ 405 return jniRegisterNativeMethods(env, "com/android/server/AlarmManagerService", 406 sMethods, NELEM(sMethods)); 407} 408 409} /* namespace android */ 410