com_android_server_AlarmManagerService.cpp revision 9158825f9c41869689d6b1786d7c7aa8bdd524ce
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 40namespace android { 41 42static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1; 43static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = { 44 CLOCK_REALTIME_ALARM, 45 CLOCK_REALTIME, 46 CLOCK_BOOTTIME_ALARM, 47 CLOCK_BOOTTIME, 48 CLOCK_MONOTONIC, 49 CLOCK_REALTIME, 50}; 51/* to match the legacy alarm driver implementation, we need an extra 52 CLOCK_REALTIME fd which exists specifically to be canceled on RTC changes */ 53 54class AlarmImpl 55{ 56public: 57 AlarmImpl(int *fds, size_t n_fds); 58 virtual ~AlarmImpl(); 59 60 virtual int set(int type, struct timespec *ts) = 0; 61 virtual int waitForAlarm() = 0; 62 63protected: 64 int *fds; 65 size_t n_fds; 66}; 67 68class AlarmImplAlarmDriver : public AlarmImpl 69{ 70public: 71 AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { } 72 73 int set(int type, struct timespec *ts); 74 int waitForAlarm(); 75}; 76 77class AlarmImplTimerFd : public AlarmImpl 78{ 79public: 80 AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd) : 81 AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd) { } 82 ~AlarmImplTimerFd(); 83 84 int set(int type, struct timespec *ts); 85 int waitForAlarm(); 86 87private: 88 int epollfd; 89}; 90 91AlarmImpl::AlarmImpl(int *fds_, size_t n_fds) : fds(new int[n_fds]), 92 n_fds(n_fds) 93{ 94 memcpy(fds, fds_, n_fds * sizeof(fds[0])); 95} 96 97AlarmImpl::~AlarmImpl() 98{ 99 for (size_t i = 0; i < n_fds; i++) { 100 close(fds[i]); 101 } 102 delete [] fds; 103} 104 105int AlarmImplAlarmDriver::set(int type, struct timespec *ts) 106{ 107 return ioctl(fds[0], ANDROID_ALARM_SET(type), ts); 108} 109 110int AlarmImplAlarmDriver::waitForAlarm() 111{ 112 return ioctl(fds[0], ANDROID_ALARM_WAIT); 113} 114 115AlarmImplTimerFd::~AlarmImplTimerFd() 116{ 117 for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { 118 epoll_ctl(epollfd, EPOLL_CTL_DEL, fds[i], NULL); 119 } 120 close(epollfd); 121} 122 123int AlarmImplTimerFd::set(int type, struct timespec *ts) 124{ 125 if (type > ANDROID_ALARM_TYPE_COUNT) { 126 errno = EINVAL; 127 return -1; 128 } 129 130 if (!ts->tv_nsec && !ts->tv_sec) { 131 ts->tv_nsec = 1; 132 } 133 /* timerfd interprets 0 = disarm, so replace with a practically 134 equivalent deadline of 1 ns */ 135 136 struct itimerspec spec; 137 memset(&spec, 0, sizeof(spec)); 138 memcpy(&spec.it_value, ts, sizeof(spec.it_value)); 139 140 return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL); 141} 142 143int AlarmImplTimerFd::waitForAlarm() 144{ 145 epoll_event events[N_ANDROID_TIMERFDS]; 146 147 int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1); 148 if (nevents < 0) { 149 return nevents; 150 } 151 152 int result = 0; 153 for (int i = 0; i < nevents; i++) { 154 uint32_t alarm_idx = events[i].data.u32; 155 uint64_t unused; 156 ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused)); 157 if (err < 0) { 158 if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) { 159 result |= ANDROID_ALARM_TIME_CHANGE_MASK; 160 } else { 161 return err; 162 } 163 } else { 164 result |= (1 << alarm_idx); 165 } 166 } 167 168 return result; 169} 170 171static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest) 172{ 173 struct timezone tz; 174 175 tz.tz_minuteswest = minswest; 176 tz.tz_dsttime = 0; 177 178 int result = settimeofday(NULL, &tz); 179 if (result < 0) { 180 ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno)); 181 return -1; 182 } else { 183 ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest); 184 } 185 186 return 0; 187} 188 189static jlong init_alarm_driver() 190{ 191 int fd = open("/dev/alarm", O_RDWR); 192 if (fd < 0) { 193 ALOGV("opening alarm driver failed: %s", strerror(errno)); 194 return 0; 195 } 196 197 AlarmImpl *ret = new AlarmImplAlarmDriver(fd); 198 return reinterpret_cast<jlong>(ret); 199} 200 201static jlong init_timerfd() 202{ 203 int epollfd; 204 int fds[N_ANDROID_TIMERFDS]; 205 206 epollfd = epoll_create(N_ANDROID_TIMERFDS); 207 if (epollfd < 0) { 208 ALOGV("epoll_create(%u) failed: %s", N_ANDROID_TIMERFDS, 209 strerror(errno)); 210 return 0; 211 } 212 213 for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { 214 fds[i] = timerfd_create(android_alarm_to_clockid[i], 0); 215 if (fds[i] < 0) { 216 ALOGV("timerfd_create(%u) failed: %s", android_alarm_to_clockid[i], 217 strerror(errno)); 218 close(epollfd); 219 for (size_t j = 0; j < i; j++) { 220 close(fds[j]); 221 } 222 return 0; 223 } 224 } 225 226 AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd); 227 228 for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { 229 epoll_event event; 230 event.events = EPOLLIN | EPOLLWAKEUP; 231 event.data.u32 = i; 232 233 int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event); 234 if (err < 0) { 235 ALOGV("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno)); 236 delete ret; 237 return 0; 238 } 239 } 240 241 struct itimerspec spec; 242 memset(&spec, 0, sizeof(spec)); 243 /* 0 = disarmed; the timerfd doesn't need to be armed to get 244 RTC change notifications, just set up as cancelable */ 245 246 int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT], 247 TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL); 248 if (err < 0) { 249 ALOGV("timerfd_settime() failed: %s", strerror(errno)); 250 delete ret; 251 return 0; 252 } 253 254 return reinterpret_cast<jlong>(ret); 255} 256 257static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject) 258{ 259 jlong ret = init_alarm_driver(); 260 if (ret) { 261 return ret; 262 } 263 264 return init_timerfd(); 265} 266 267static void android_server_AlarmManagerService_close(JNIEnv*, jobject, jlong nativeData) 268{ 269 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); 270 delete impl; 271} 272 273static void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds) 274{ 275 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); 276 struct timespec ts; 277 ts.tv_sec = seconds; 278 ts.tv_nsec = nanoseconds; 279 280 int result = impl->set(type, &ts); 281 if (result < 0) 282 { 283 ALOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno)); 284 } 285} 286 287static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jlong nativeData) 288{ 289 AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); 290 int result = 0; 291 292 do 293 { 294 result = impl->waitForAlarm(); 295 } while (result < 0 && errno == EINTR); 296 297 if (result < 0) 298 { 299 ALOGE("Unable to wait on alarm: %s\n", strerror(errno)); 300 return 0; 301 } 302 303 return result; 304} 305 306static JNINativeMethod sMethods[] = { 307 /* name, signature, funcPtr */ 308 {"init", "()J", (void*)android_server_AlarmManagerService_init}, 309 {"close", "(J)V", (void*)android_server_AlarmManagerService_close}, 310 {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set}, 311 {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm}, 312 {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone}, 313}; 314 315int register_android_server_AlarmManagerService(JNIEnv* env) 316{ 317 return jniRegisterNativeMethods(env, "com/android/server/AlarmManagerService", 318 sMethods, NELEM(sMethods)); 319} 320 321} /* namespace android */ 322