Loading services/core/jni/com_android_server_AlarmManagerService.cpp +41 −136 Original line number Diff line number Diff line Loading @@ -39,39 +39,26 @@ #include <linux/ioctl.h> #include <linux/rtc.h> #include <array> #include <memory> //-------------------------------------------------------------------------- // The android_alarm.h header has been deleted from the kernel headers. // Add only the parts still needed, this should be deleted in the future. #include <linux/ioctl.h> enum android_alarm_type { ANDROID_ALARM_RTC_WAKEUP, ANDROID_ALARM_RTC, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, ANDROID_ALARM_ELAPSED_REALTIME, ANDROID_ALARM_SYSTEMTIME, ANDROID_ALARM_TYPE_COUNT, }; enum android_alarm_return_flags { ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP, ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK = 1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, ANDROID_ALARM_ELAPSED_REALTIME_MASK = 1U << ANDROID_ALARM_ELAPSED_REALTIME, ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME, ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16 }; #define ALARM_IOW(c,type,size) _IOW('a', (c) | ((type) << 4), size) #define ANDROID_ALARM_WAIT _IO('a', 1) #define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) #define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) //-------------------------------------------------------------------------- namespace android { static constexpr int ANDROID_ALARM_TIME_CHANGE_MASK = 1 << 16; /** * The AlarmManager alarm constants: * * RTC_WAKEUP * RTC * REALTIME_WAKEUP * REALTIME * SYSTEMTIME (only defined in old alarm driver header, possibly unused?) * * We also need an extra CLOCK_REALTIME fd which exists specifically to be * canceled on RTC changes. */ static const size_t ANDROID_ALARM_TYPE_COUNT = 5; 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, Loading @@ -81,98 +68,39 @@ static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = { 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 setTime(struct timeval *tv) = 0; virtual int waitForAlarm() = 0; typedef std::array<int, N_ANDROID_TIMERFDS> TimerFds; protected: int *fds; size_t n_fds; }; class AlarmImplAlarmDriver : public AlarmImpl { public: explicit AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { } int set(int type, struct timespec *ts); int setTime(struct timeval *tv); int waitForAlarm(); }; class AlarmImplTimerFd : public AlarmImpl class AlarmImpl { public: AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd, int rtc_id) : AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd), rtc_id(rtc_id) { } ~AlarmImplTimerFd(); AlarmImpl(const TimerFds &fds, int epollfd, int rtc_id) : fds{fds}, epollfd{epollfd}, rtc_id{rtc_id} { } ~AlarmImpl(); int set(int type, struct timespec *ts); int setTime(struct timeval *tv); int waitForAlarm(); private: int epollfd; int rtc_id; const TimerFds fds; const int epollfd; const int rtc_id; }; 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::setTime(struct timeval *tv) { struct timespec ts; int res; ts.tv_sec = tv->tv_sec; ts.tv_nsec = tv->tv_usec * 1000; res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts); if (res < 0) ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno)); return res; } int AlarmImplAlarmDriver::waitForAlarm() { return ioctl(fds[0], ANDROID_ALARM_WAIT); for (auto fd : fds) { epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, nullptr); close(fd); } 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) int AlarmImpl::set(int type, struct timespec *ts) { if (type > ANDROID_ALARM_TYPE_COUNT) { if (static_cast<size_t>(type) > ANDROID_ALARM_TYPE_COUNT) { errno = EINVAL; return -1; } Loading @@ -190,7 +118,7 @@ int AlarmImplTimerFd::set(int type, struct timespec *ts) return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL); } int AlarmImplTimerFd::setTime(struct timeval *tv) int AlarmImpl::setTime(struct timeval *tv) { struct rtc_time rtc; struct tm tm, *gmtime_res; Loading Loading @@ -241,7 +169,7 @@ done: return res; } int AlarmImplTimerFd::waitForAlarm() int AlarmImpl::waitForAlarm() { epoll_event events[N_ANDROID_TIMERFDS]; Loading Loading @@ -311,25 +239,12 @@ static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobjec 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 const char rtc_sysfs[] = "/sys/class/rtc"; static bool rtc_is_hctosys(unsigned int rtc_id) { android::String8 hctosys_path = String8::format("%s/rtc%u/hctosys", rtc_sysfs, rtc_id); FILE *file = fopen(hctosys_path.string(), "re"); if (!file) { ALOGE("failed to open %s: %s", hctosys_path.string(), strerror(errno)); Loading Loading @@ -383,22 +298,22 @@ static int wall_clock_rtc() return -1; } static jlong init_timerfd() static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject) { int epollfd; int fds[N_ANDROID_TIMERFDS]; TimerFds fds; epollfd = epoll_create(N_ANDROID_TIMERFDS); epollfd = epoll_create(fds.size()); if (epollfd < 0) { ALOGV("epoll_create(%zu) failed: %s", N_ANDROID_TIMERFDS, ALOGE("epoll_create(%zu) failed: %s", fds.size(), strerror(errno)); return 0; } for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { for (size_t i = 0; i < fds.size(); 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], ALOGE("timerfd_create(%u) failed: %s", android_alarm_to_clockid[i], strerror(errno)); close(epollfd); for (size_t j = 0; j < i; j++) { Loading @@ -408,16 +323,16 @@ static jlong init_timerfd() } } AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd, wall_clock_rtc()); AlarmImpl *ret = new AlarmImpl(fds, epollfd, wall_clock_rtc()); for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { for (size_t i = 0; i < fds.size(); 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)); ALOGE("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno)); delete ret; return 0; } Loading @@ -431,7 +346,7 @@ static jlong init_timerfd() 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)); ALOGE("timerfd_settime() failed: %s", strerror(errno)); delete ret; return 0; } Loading @@ -439,16 +354,6 @@ static jlong init_timerfd() 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); Loading Loading
services/core/jni/com_android_server_AlarmManagerService.cpp +41 −136 Original line number Diff line number Diff line Loading @@ -39,39 +39,26 @@ #include <linux/ioctl.h> #include <linux/rtc.h> #include <array> #include <memory> //-------------------------------------------------------------------------- // The android_alarm.h header has been deleted from the kernel headers. // Add only the parts still needed, this should be deleted in the future. #include <linux/ioctl.h> enum android_alarm_type { ANDROID_ALARM_RTC_WAKEUP, ANDROID_ALARM_RTC, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, ANDROID_ALARM_ELAPSED_REALTIME, ANDROID_ALARM_SYSTEMTIME, ANDROID_ALARM_TYPE_COUNT, }; enum android_alarm_return_flags { ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP, ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK = 1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, ANDROID_ALARM_ELAPSED_REALTIME_MASK = 1U << ANDROID_ALARM_ELAPSED_REALTIME, ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME, ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16 }; #define ALARM_IOW(c,type,size) _IOW('a', (c) | ((type) << 4), size) #define ANDROID_ALARM_WAIT _IO('a', 1) #define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) #define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) //-------------------------------------------------------------------------- namespace android { static constexpr int ANDROID_ALARM_TIME_CHANGE_MASK = 1 << 16; /** * The AlarmManager alarm constants: * * RTC_WAKEUP * RTC * REALTIME_WAKEUP * REALTIME * SYSTEMTIME (only defined in old alarm driver header, possibly unused?) * * We also need an extra CLOCK_REALTIME fd which exists specifically to be * canceled on RTC changes. */ static const size_t ANDROID_ALARM_TYPE_COUNT = 5; 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, Loading @@ -81,98 +68,39 @@ static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = { 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 setTime(struct timeval *tv) = 0; virtual int waitForAlarm() = 0; typedef std::array<int, N_ANDROID_TIMERFDS> TimerFds; protected: int *fds; size_t n_fds; }; class AlarmImplAlarmDriver : public AlarmImpl { public: explicit AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { } int set(int type, struct timespec *ts); int setTime(struct timeval *tv); int waitForAlarm(); }; class AlarmImplTimerFd : public AlarmImpl class AlarmImpl { public: AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd, int rtc_id) : AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd), rtc_id(rtc_id) { } ~AlarmImplTimerFd(); AlarmImpl(const TimerFds &fds, int epollfd, int rtc_id) : fds{fds}, epollfd{epollfd}, rtc_id{rtc_id} { } ~AlarmImpl(); int set(int type, struct timespec *ts); int setTime(struct timeval *tv); int waitForAlarm(); private: int epollfd; int rtc_id; const TimerFds fds; const int epollfd; const int rtc_id; }; 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::setTime(struct timeval *tv) { struct timespec ts; int res; ts.tv_sec = tv->tv_sec; ts.tv_nsec = tv->tv_usec * 1000; res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts); if (res < 0) ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno)); return res; } int AlarmImplAlarmDriver::waitForAlarm() { return ioctl(fds[0], ANDROID_ALARM_WAIT); for (auto fd : fds) { epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, nullptr); close(fd); } 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) int AlarmImpl::set(int type, struct timespec *ts) { if (type > ANDROID_ALARM_TYPE_COUNT) { if (static_cast<size_t>(type) > ANDROID_ALARM_TYPE_COUNT) { errno = EINVAL; return -1; } Loading @@ -190,7 +118,7 @@ int AlarmImplTimerFd::set(int type, struct timespec *ts) return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL); } int AlarmImplTimerFd::setTime(struct timeval *tv) int AlarmImpl::setTime(struct timeval *tv) { struct rtc_time rtc; struct tm tm, *gmtime_res; Loading Loading @@ -241,7 +169,7 @@ done: return res; } int AlarmImplTimerFd::waitForAlarm() int AlarmImpl::waitForAlarm() { epoll_event events[N_ANDROID_TIMERFDS]; Loading Loading @@ -311,25 +239,12 @@ static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobjec 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 const char rtc_sysfs[] = "/sys/class/rtc"; static bool rtc_is_hctosys(unsigned int rtc_id) { android::String8 hctosys_path = String8::format("%s/rtc%u/hctosys", rtc_sysfs, rtc_id); FILE *file = fopen(hctosys_path.string(), "re"); if (!file) { ALOGE("failed to open %s: %s", hctosys_path.string(), strerror(errno)); Loading Loading @@ -383,22 +298,22 @@ static int wall_clock_rtc() return -1; } static jlong init_timerfd() static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject) { int epollfd; int fds[N_ANDROID_TIMERFDS]; TimerFds fds; epollfd = epoll_create(N_ANDROID_TIMERFDS); epollfd = epoll_create(fds.size()); if (epollfd < 0) { ALOGV("epoll_create(%zu) failed: %s", N_ANDROID_TIMERFDS, ALOGE("epoll_create(%zu) failed: %s", fds.size(), strerror(errno)); return 0; } for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { for (size_t i = 0; i < fds.size(); 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], ALOGE("timerfd_create(%u) failed: %s", android_alarm_to_clockid[i], strerror(errno)); close(epollfd); for (size_t j = 0; j < i; j++) { Loading @@ -408,16 +323,16 @@ static jlong init_timerfd() } } AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd, wall_clock_rtc()); AlarmImpl *ret = new AlarmImpl(fds, epollfd, wall_clock_rtc()); for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { for (size_t i = 0; i < fds.size(); 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)); ALOGE("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno)); delete ret; return 0; } Loading @@ -431,7 +346,7 @@ static jlong init_timerfd() 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)); ALOGE("timerfd_settime() failed: %s", strerror(errno)); delete ret; return 0; } Loading @@ -439,16 +354,6 @@ static jlong init_timerfd() 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); Loading