diff options
Diffstat (limited to 'services/jni/com_android_server_AlarmManagerService.cpp')
-rw-r--r-- | services/jni/com_android_server_AlarmManagerService.cpp | 321 |
1 files changed, 0 insertions, 321 deletions
diff --git a/services/jni/com_android_server_AlarmManagerService.cpp b/services/jni/com_android_server_AlarmManagerService.cpp deleted file mode 100644 index 342515b..0000000 --- a/services/jni/com_android_server_AlarmManagerService.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/* //device/libs/android_runtime/android_server_AlarmManagerService.cpp -** -** Copyright 2006, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#define LOG_TAG "AlarmManagerService" - -#include "JNIHelp.h" -#include "jni.h" -#include <utils/Log.h> -#include <utils/misc.h> - -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <sys/epoll.h> -#include <sys/timerfd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <arpa/inet.h> -#include <netinet/in.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <linux/ioctl.h> -#include <linux/android_alarm.h> - -namespace android { - -static const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1; -static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = { - CLOCK_REALTIME_ALARM, - CLOCK_REALTIME, - CLOCK_BOOTTIME_ALARM, - CLOCK_BOOTTIME, - CLOCK_MONOTONIC, - CLOCK_REALTIME, -}; -/* to match the legacy alarm driver implementation, we need an extra - CLOCK_REALTIME fd which exists specifically to be canceled on RTC changes */ - -class AlarmImpl -{ -public: - AlarmImpl(int *fds, size_t n_fds); - virtual ~AlarmImpl(); - - virtual int set(int type, struct timespec *ts) = 0; - virtual int waitForAlarm() = 0; - -protected: - int *fds; - size_t n_fds; -}; - -class AlarmImplAlarmDriver : public AlarmImpl -{ -public: - AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { } - - int set(int type, struct timespec *ts); - int waitForAlarm(); -}; - -class AlarmImplTimerFd : public AlarmImpl -{ -public: - AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd) : - AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd) { } - ~AlarmImplTimerFd(); - - int set(int type, struct timespec *ts); - int waitForAlarm(); - -private: - int epollfd; -}; - -AlarmImpl::AlarmImpl(int *fds_, size_t n_fds) : fds(new int[n_fds]), - n_fds(n_fds) -{ - memcpy(fds, fds_, n_fds * sizeof(fds[0])); -} - -AlarmImpl::~AlarmImpl() -{ - for (size_t i = 0; i < n_fds; i++) { - close(fds[i]); - } - delete [] fds; -} - -int AlarmImplAlarmDriver::set(int type, struct timespec *ts) -{ - return ioctl(fds[0], ANDROID_ALARM_SET(type), ts); -} - -int AlarmImplAlarmDriver::waitForAlarm() -{ - return ioctl(fds[0], ANDROID_ALARM_WAIT); -} - -AlarmImplTimerFd::~AlarmImplTimerFd() -{ - for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { - epoll_ctl(epollfd, EPOLL_CTL_DEL, fds[i], NULL); - } - close(epollfd); -} - -int AlarmImplTimerFd::set(int type, struct timespec *ts) -{ - if (type > ANDROID_ALARM_TYPE_COUNT) { - errno = EINVAL; - return -1; - } - - if (!ts->tv_nsec && !ts->tv_sec) { - ts->tv_nsec = 1; - } - /* timerfd interprets 0 = disarm, so replace with a practically - equivalent deadline of 1 ns */ - - struct itimerspec spec; - memset(&spec, 0, sizeof(spec)); - memcpy(&spec.it_value, ts, sizeof(spec.it_value)); - - return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL); -} - -int AlarmImplTimerFd::waitForAlarm() -{ - epoll_event events[N_ANDROID_TIMERFDS]; - - int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1); - if (nevents < 0) { - return nevents; - } - - int result = 0; - for (int i = 0; i < nevents; i++) { - uint32_t alarm_idx = events[i].data.u32; - uint64_t unused; - ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused)); - if (err < 0) { - if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) { - result |= ANDROID_ALARM_TIME_CHANGE_MASK; - } else { - return err; - } - } else { - result |= (1 << alarm_idx); - } - } - - return result; -} - -static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest) -{ - struct timezone tz; - - tz.tz_minuteswest = minswest; - tz.tz_dsttime = 0; - - int result = settimeofday(NULL, &tz); - if (result < 0) { - ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno)); - return -1; - } else { - ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest); - } - - return 0; -} - -static jlong init_alarm_driver() -{ - int fd = open("/dev/alarm", O_RDWR); - if (fd < 0) { - ALOGV("opening alarm driver failed: %s", strerror(errno)); - return 0; - } - - AlarmImpl *ret = new AlarmImplAlarmDriver(fd); - return reinterpret_cast<jlong>(ret); -} - -static jlong init_timerfd() -{ - int epollfd; - int fds[N_ANDROID_TIMERFDS]; - - epollfd = epoll_create(N_ANDROID_TIMERFDS); - if (epollfd < 0) { - ALOGV("epoll_create(%u) failed: %s", N_ANDROID_TIMERFDS, - strerror(errno)); - return 0; - } - - for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { - fds[i] = timerfd_create(android_alarm_to_clockid[i], 0); - if (fds[i] < 0) { - ALOGV("timerfd_create(%u) failed: %s", android_alarm_to_clockid[i], - strerror(errno)); - close(epollfd); - for (size_t j = 0; j < i; j++) { - close(fds[j]); - } - return 0; - } - } - - AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd); - - for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { - epoll_event event; - event.events = EPOLLIN | EPOLLWAKEUP; - event.data.u32 = i; - - int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event); - if (err < 0) { - ALOGV("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno)); - delete ret; - return 0; - } - } - - struct itimerspec spec; - memset(&spec, 0, sizeof(spec)); - /* 0 = disarmed; the timerfd doesn't need to be armed to get - RTC change notifications, just set up as cancelable */ - - int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT], - TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL); - if (err < 0) { - ALOGV("timerfd_settime() failed: %s", strerror(errno)); - delete ret; - return 0; - } - - return reinterpret_cast<jlong>(ret); -} - -static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject) -{ - jlong ret = init_alarm_driver(); - if (ret) { - return ret; - } - - return init_timerfd(); -} - -static void android_server_AlarmManagerService_close(JNIEnv*, jobject, jlong nativeData) -{ - AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); - delete impl; -} - -static void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds) -{ - AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); - struct timespec ts; - ts.tv_sec = seconds; - ts.tv_nsec = nanoseconds; - - int result = impl->set(type, &ts); - if (result < 0) - { - ALOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno)); - } -} - -static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jlong nativeData) -{ - AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData); - int result = 0; - - do - { - result = impl->waitForAlarm(); - } while (result < 0 && errno == EINTR); - - if (result < 0) - { - ALOGE("Unable to wait on alarm: %s\n", strerror(errno)); - return 0; - } - - return result; -} - -static JNINativeMethod sMethods[] = { - /* name, signature, funcPtr */ - {"init", "()J", (void*)android_server_AlarmManagerService_init}, - {"close", "(J)V", (void*)android_server_AlarmManagerService_close}, - {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set}, - {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm}, - {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone}, -}; - -int register_android_server_AlarmManagerService(JNIEnv* env) -{ - return jniRegisterNativeMethods(env, "com/android/server/AlarmManagerService", - sMethods, NELEM(sMethods)); -} - -} /* namespace android */ |