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