Revert "AlarmManagerService: remove legacy /dev/alarm support"
This reverts commit f68cdb9cb4841765d9d55d4a95259e9c3bb3ecc1.
Change-Id: I13e954656771f32c6156b4c4adb52922bcd0717a
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index 36105bd..407c072 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -37,28 +37,13 @@
#include <errno.h>
#include <unistd.h>
#include <linux/ioctl.h>
+#include <linux/android_alarm.h>
#include <linux/rtc.h>
-#include <array>
#include <memory>
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,
@@ -68,39 +53,98 @@
CLOCK_MONOTONIC,
CLOCK_REALTIME,
};
-
-typedef std::array<int, N_ANDROID_TIMERFDS> TimerFds;
+/* 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(const TimerFds &fds, int epollfd, int rtc_id) :
- fds{fds}, epollfd{epollfd}, rtc_id{rtc_id} { }
- ~AlarmImpl();
+ 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;
+
+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
+{
+public:
+ AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd, int rtc_id) :
+ AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd), rtc_id(rtc_id) { }
+ ~AlarmImplTimerFd();
int set(int type, struct timespec *ts);
int setTime(struct timeval *tv);
int waitForAlarm();
private:
- const TimerFds fds;
- const int epollfd;
- const int rtc_id;
+ int epollfd;
+ 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 (auto fd : fds) {
- epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, nullptr);
- close(fd);
+ 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);
+}
+
+AlarmImplTimerFd::~AlarmImplTimerFd()
+{
+ for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
+ epoll_ctl(epollfd, EPOLL_CTL_DEL, fds[i], NULL);
+ }
close(epollfd);
}
-int AlarmImpl::set(int type, struct timespec *ts)
+int AlarmImplTimerFd::set(int type, struct timespec *ts)
{
- if (static_cast<size_t>(type) > ANDROID_ALARM_TYPE_COUNT) {
+ if (type > ANDROID_ALARM_TYPE_COUNT) {
errno = EINVAL;
return -1;
}
@@ -118,7 +162,7 @@
return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
}
-int AlarmImpl::setTime(struct timeval *tv)
+int AlarmImplTimerFd::setTime(struct timeval *tv)
{
struct rtc_time rtc;
struct tm tm, *gmtime_res;
@@ -169,7 +213,7 @@
return res;
}
-int AlarmImpl::waitForAlarm()
+int AlarmImplTimerFd::waitForAlarm()
{
epoll_event events[N_ANDROID_TIMERFDS];
@@ -239,12 +283,25 @@
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));
@@ -298,22 +355,22 @@
return -1;
}
-static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject)
+static jlong init_timerfd()
{
int epollfd;
- TimerFds fds;
+ int fds[N_ANDROID_TIMERFDS];
- epollfd = epoll_create(fds.size());
+ epollfd = epoll_create(N_ANDROID_TIMERFDS);
if (epollfd < 0) {
- ALOGE("epoll_create(%zu) failed: %s", fds.size(),
+ ALOGV("epoll_create(%zu) failed: %s", N_ANDROID_TIMERFDS,
strerror(errno));
return 0;
}
- for (size_t i = 0; i < fds.size(); i++) {
+ for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
fds[i] = timerfd_create(android_alarm_to_clockid[i], 0);
if (fds[i] < 0) {
- ALOGE("timerfd_create(%u) failed: %s", android_alarm_to_clockid[i],
+ ALOGV("timerfd_create(%u) failed: %s", android_alarm_to_clockid[i],
strerror(errno));
close(epollfd);
for (size_t j = 0; j < i; j++) {
@@ -323,16 +380,16 @@
}
}
- AlarmImpl *ret = new AlarmImpl(fds, epollfd, wall_clock_rtc());
+ AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd, wall_clock_rtc());
- for (size_t i = 0; i < fds.size(); i++) {
+ 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) {
- ALOGE("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno));
+ ALOGV("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno));
delete ret;
return 0;
}
@@ -346,7 +403,7 @@
int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT],
TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL);
if (err < 0) {
- ALOGE("timerfd_settime() failed: %s", strerror(errno));
+ ALOGV("timerfd_settime() failed: %s", strerror(errno));
delete ret;
return 0;
}
@@ -354,6 +411,16 @@
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);