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 45namespace android { 46 47static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1; 48static 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 59class AlarmImpl 60{ 61public: 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 69protected: 70 int *fds; 71 size_t n_fds; 72}; 73 74class AlarmImplAlarmDriver : public AlarmImpl 75{ 76public: 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 84class AlarmImplTimerFd : public AlarmImpl 85{ 86public: 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 95private: 96 int epollfd; 97 int rtc_id; 98}; 99 100AlarmImpl::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 106AlarmImpl::~AlarmImpl() 107{ 108 for (size_t i = 0; i < n_fds; i++) { 109 close(fds[i]); 110 } 111 delete [] fds; 112} 113 114int AlarmImplAlarmDriver::set(int type, struct timespec *ts) 115{ 116 return ioctl(fds[0], ANDROID_ALARM_SET(type), ts); 117} 118 119int 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 132int AlarmImplAlarmDriver::waitForAlarm() 133{ 134 return ioctl(fds[0], ANDROID_ALARM_WAIT); 135} 136 137AlarmImplTimerFd::~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 145int 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 165int 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)); 211done: 212 close(fd); 213 return res; 214} 215 216int 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 244static 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 268static 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 286static 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 298static const char rtc_sysfs[] = "/sys/class/rtc"; 299 300static 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 326static 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 358static 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 414static 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 424static void android_server_AlarmManagerService_close(JNIEnv*, jobject, jlong nativeData) 425{ 426 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); 427 delete impl; 428} 429 430static 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 446static 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 465static 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 475int 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