aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMister Oyster <oysterized@gmail.com>2018-01-07 14:25:22 +0100
committerMister Oyster <oysterized@gmail.com>2018-01-07 14:25:22 +0100
commitd2be7057fdb22fefa828fba948dc02c7bffccfe1 (patch)
treea0522159c2812e370a905cab56b941ef8f7ea97d
parent6470d7e9300829516b6fbe155082cc9ff11bf867 (diff)
patch: fix dev-alarm support
-rw-r--r--patches/frameworks/base/0002-mtk-bring-back-legacy-dev-alarm-support.patch312
1 files changed, 312 insertions, 0 deletions
diff --git a/patches/frameworks/base/0002-mtk-bring-back-legacy-dev-alarm-support.patch b/patches/frameworks/base/0002-mtk-bring-back-legacy-dev-alarm-support.patch
new file mode 100644
index 0000000..b9d6e31
--- /dev/null
+++ b/patches/frameworks/base/0002-mtk-bring-back-legacy-dev-alarm-support.patch
@@ -0,0 +1,312 @@
+From b51abbffc027dee8baa7c5552fc3b20407477275 Mon Sep 17 00:00:00 2001
+From: Mister Oyster <oysterized@gmail.com>
+Date: Sun, 7 Jan 2018 14:22:52 +0100
+Subject: [PATCH] mtk: bring back legacy /dev/alarm support
+
+Revert "AlarmManagerService: explain some timerfd_create() failures"
+This reverts commit a0126e0857481866dab5060384d611c83ca53d0e.
+
+Revert "AlarmManagerService: remove legacy /dev/alarm support"
+This reverts commit d7151c06f11c05ad3dcab175a6e4b4ea694dab96.
+
+Revert "Remove dependency on android_alarm.h."
+This reverts commit 338893e47ed8e2a913e5def987469647809cdbc6.
+---
+ .../jni/com_android_server_AlarmManagerService.cpp | 176 +++++++++++++--------
+ 1 file changed, 109 insertions(+), 67 deletions(-)
+
+diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
+index 3a0273d8c3c..407c0726e52 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 @@ static const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = {
+ 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 @@ int AlarmImpl::set(int type, struct timespec *ts)
+ 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 @@ done:
+ return res;
+ }
+
+-int AlarmImpl::waitForAlarm()
++int AlarmImplTimerFd::waitForAlarm()
+ {
+ epoll_event events[N_ANDROID_TIMERFDS];
+
+@@ -239,12 +283,25 @@ 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));
+@@ -298,48 +355,23 @@ static int wall_clock_rtc()
+ return -1;
+ }
+
+-static void log_timerfd_create_error(clockid_t id)
+-{
+- if (errno == EINVAL) {
+- switch (id) {
+- case CLOCK_REALTIME_ALARM:
+- case CLOCK_BOOTTIME_ALARM:
+- ALOGE("kernel missing required commits:");
+- ALOGE("https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=6cffe00f7d4e24679eae6b7aae4caaf915288256");
+- ALOGE("https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=11ffa9d6065f344a9bd769a2452f26f2f671e5f8");
+- LOG_ALWAYS_FATAL("kernel does not support timerfd_create() with alarm timers");
+- break;
+-
+- case CLOCK_BOOTTIME:
+- ALOGE("kernel missing required commit:");
+- ALOGE("https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=4a2378a943f09907fb1ae35c15de917f60289c14");
+- LOG_ALWAYS_FATAL("kernel does not support timerfd_create(CLOCK_BOOTTIME)");
+- break;
+-
+- default:
+- break;
+- }
+- }
+-
+- ALOGE("timerfd_create(%u) failed: %s", id, strerror(errno));
+-}
+-
+-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) {
+- log_timerfd_create_error(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++) {
+ close(fds[j]);
+@@ -348,16 +380,16 @@ static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject)
+ }
+ }
+
+- 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;
+ }
+@@ -371,7 +403,7 @@ static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject)
+ 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;
+ }
+@@ -379,6 +411,16 @@ static jlong android_server_AlarmManagerService_init(JNIEnv*, jobject)
+ 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);
+--
+2.14.1
+