diff options
author | Greg Hackmann <ghackmann@google.com> | 2015-01-13 20:43:35 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-01-13 20:43:36 +0000 |
commit | 41ef80e7ff739d863ea5df0e129e54f953545212 (patch) | |
tree | e99cf4f2ed5efd25c966384acc6495e2d586e547 | |
parent | 66b4d48469c74f7dd889f3f685b436fcb957bf16 (diff) | |
parent | 0eb5826830592695f4a5b4d1dba18e0ca991163e (diff) | |
download | frameworks_base-41ef80e7ff739d863ea5df0e129e54f953545212.zip frameworks_base-41ef80e7ff739d863ea5df0e129e54f953545212.tar.gz frameworks_base-41ef80e7ff739d863ea5df0e129e54f953545212.tar.bz2 |
Merge "Find wall clock RTC through sysfs"
-rw-r--r-- | services/core/jni/com_android_server_AlarmManagerService.cpp | 80 |
1 files changed, 75 insertions, 5 deletions
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp index 3d981ab..3fd0f84 100644 --- a/services/core/jni/com_android_server_AlarmManagerService.cpp +++ b/services/core/jni/com_android_server_AlarmManagerService.cpp @@ -21,7 +21,9 @@ #include "jni.h" #include <utils/Log.h> #include <utils/misc.h> +#include <utils/String8.h> +#include <dirent.h> #include <fcntl.h> #include <stdio.h> #include <string.h> @@ -80,8 +82,8 @@ public: class AlarmImplTimerFd : public AlarmImpl { public: - AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd) : - AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd) { } + 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); @@ -90,6 +92,7 @@ public: private: int epollfd; + int rtc_id; }; AlarmImpl::AlarmImpl(int *fds_, size_t n_fds) : fds(new int[n_fds]), @@ -170,9 +173,16 @@ int AlarmImplTimerFd::setTime(struct timeval *tv) return -1; } - fd = open("/dev/rtc0", O_RDWR); + if (rtc_id < 0) { + ALOGV("Not setting RTC because wall clock RTC was not found"); + errno = ENODEV; + return -1; + } + + android::String8 rtc_dev = String8::format("/dev/rtc%d", rtc_id); + fd = open(rtc_dev.string(), O_RDWR); if (fd < 0) { - ALOGV("Unable to open RTC driver: %s\n", strerror(errno)); + ALOGV("Unable to open %s: %s\n", rtc_dev.string(), strerror(errno)); return res; } @@ -283,6 +293,66 @@ static jlong init_alarm_driver() 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)); + return false; + } + + unsigned int hctosys; + bool ret = false; + int err = fscanf(file, "%u", &hctosys); + if (err == EOF) + ALOGE("failed to read from %s: %s", hctosys_path.string(), + strerror(errno)); + else if (err == 0) + ALOGE("%s did not have expected contents", hctosys_path.string()); + else + ret = hctosys; + + fclose(file); + return ret; +} + +static int wall_clock_rtc() +{ + DIR *dir = opendir(rtc_sysfs); + if (!dir) { + ALOGE("failed to open %s: %s", rtc_sysfs, strerror(errno)); + return -1; + } + + struct dirent *dirent; + while (errno = 0, dirent = readdir(dir)) { + unsigned int rtc_id; + int matched = sscanf(dirent->d_name, "rtc%u", &rtc_id); + + if (matched < 0) + break; + else if (matched != 1) + continue; + + if (rtc_is_hctosys(rtc_id)) { + ALOGV("found wall clock RTC %u", rtc_id); + return rtc_id; + } + } + + if (errno == 0) + ALOGW("no wall clock RTC found"); + else + ALOGE("failed to enumerate RTCs: %s", strerror(errno)); + + return -1; +} + static jlong init_timerfd() { int epollfd; @@ -308,7 +378,7 @@ static jlong init_timerfd() } } - AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd); + AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd, wall_clock_rtc()); for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) { epoll_event event; |