com_android_server_AlarmManagerService.cpp revision 22d074643ed0d010ebfdb0fca685d65eb2632e58
19c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan/* //device/libs/android_runtime/android_server_AlarmManagerService.cpp
29c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan**
39c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan** Copyright 2006, The Android Open Source Project
49c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan**
59c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan** Licensed under the Apache License, Version 2.0 (the "License");
69c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan** you may not use this file except in compliance with the License.
79c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan** You may obtain a copy of the License at
89c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan**
99c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan**     http://www.apache.org/licenses/LICENSE-2.0
109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan**
119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan** Unless required by applicable law or agreed to in writing, software
129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan** distributed under the License is distributed on an "AS IS" BASIS,
139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan** See the License for the specific language governing permissions and
159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan** limitations under the License.
169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan*/
179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#define LOG_TAG "AlarmManagerService"
199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include "JNIHelp.h"
219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include "jni.h"
22f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync#include <utils/Log.h>
23f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync#include <utils/misc.h>
24f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync
259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include <fcntl.h>
269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include <stdio.h>
279329db04f13480ccdff013dcc00cdb96f12a921cWink Saville#include <string.h>
289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include <sys/epoll.h>
299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include <sys/timerfd.h>
309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include <sys/types.h>
319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include <sys/socket.h>
329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include <arpa/inet.h>
33cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg#include <netinet/in.h>
34cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg#include <stdlib.h>
359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include <errno.h>
369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include <unistd.h>
379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include <linux/ioctl.h>
389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include <linux/android_alarm.h>
399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan#include <linux/rtc.h>
409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyannamespace android {
429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanstatic const size_t N_ANDROID_TIMERFDS = ANDROID_ALARM_TYPE_COUNT + 1;
449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanstatic const clockid_t android_alarm_to_clockid[N_ANDROID_TIMERFDS] = {
459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    CLOCK_REALTIME_ALARM,
469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    CLOCK_REALTIME,
479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    CLOCK_BOOTTIME_ALARM,
489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    CLOCK_BOOTTIME,
499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    CLOCK_MONOTONIC,
509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    CLOCK_REALTIME,
519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan};
529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan/* to match the legacy alarm driver implementation, we need an extra
539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan   CLOCK_REALTIME fd which exists specifically to be canceled on RTC changes */
549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanclass AlarmImpl
569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanpublic:
589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    AlarmImpl(int *fds, size_t n_fds);
599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    virtual ~AlarmImpl();
609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    virtual int set(int type, struct timespec *ts) = 0;
629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    virtual int setTime(struct timeval *tv) = 0;
639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    virtual int waitForAlarm() = 0;
649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanprotected:
669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int *fds;
679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    size_t n_fds;
689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan};
699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanclass AlarmImplAlarmDriver : public AlarmImpl
719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanpublic:
739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }
749329db04f13480ccdff013dcc00cdb96f12a921cWink Saville
759329db04f13480ccdff013dcc00cdb96f12a921cWink Saville    int set(int type, struct timespec *ts);
769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int setTime(struct timeval *tv);
779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int waitForAlarm();
789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan};
799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanclass AlarmImplTimerFd : public AlarmImpl
819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanpublic:
839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    AlarmImplTimerFd(int fds[N_ANDROID_TIMERFDS], int epollfd) :
849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        AlarmImpl(fds, N_ANDROID_TIMERFDS), epollfd(epollfd) { }
859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    ~AlarmImplTimerFd();
869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int set(int type, struct timespec *ts);
889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int setTime(struct timeval *tv);
899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int waitForAlarm();
909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanprivate:
929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int epollfd;
939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan};
949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying TyanAlarmImpl::AlarmImpl(int *fds_, size_t n_fds) : fds(new int[n_fds]),
969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        n_fds(n_fds)
979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    memcpy(fds, fds_, n_fds * sizeof(fds[0]));
999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
1009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying TyanAlarmImpl::~AlarmImpl()
1029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
1039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    for (size_t i = 0; i < n_fds; i++) {
1049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        close(fds[i]);
1059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    delete [] fds;
1079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
1089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanint AlarmImplAlarmDriver::set(int type, struct timespec *ts)
1109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
1119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    return ioctl(fds[0], ANDROID_ALARM_SET(type), ts);
1129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
1139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanint AlarmImplAlarmDriver::setTime(struct timeval *tv)
1159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
1169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    struct timespec ts;
1179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int res;
1189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    ts.tv_sec = tv->tv_sec;
1209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    ts.tv_nsec = tv->tv_usec * 1000;
1219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    res = ioctl(fds[0], ANDROID_ALARM_SET_RTC, &ts);
1229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if (res < 0)
1239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
1249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    return res;
1259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
1269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanint AlarmImplAlarmDriver::waitForAlarm()
1289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
1299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    return ioctl(fds[0], ANDROID_ALARM_WAIT);
1309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
1319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying TyanAlarmImplTimerFd::~AlarmImplTimerFd()
1339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
1349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
1359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        epoll_ctl(epollfd, EPOLL_CTL_DEL, fds[i], NULL);
1369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    close(epollfd);
1389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
1399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanint AlarmImplTimerFd::set(int type, struct timespec *ts)
1419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
1429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if (type > ANDROID_ALARM_TYPE_COUNT) {
1439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        errno = EINVAL;
1449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return -1;
1459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if (!ts->tv_nsec && !ts->tv_sec) {
1489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ts->tv_nsec = 1;
1499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    /* timerfd interprets 0 = disarm, so replace with a practically
1519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan       equivalent deadline of 1 ns */
1529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    struct itimerspec spec;
1543efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    memset(&spec, 0, sizeof(spec));
1553efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    memcpy(&spec.it_value, ts, sizeof(spec.it_value));
1563efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan
1573efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
1583efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan}
1593efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan
1603efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyanint AlarmImplTimerFd::setTime(struct timeval *tv)
1613efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan{
1623efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    struct rtc_time rtc;
1633efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    struct tm tm, *gmtime_res;
1643efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    int fd;
1659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int res;
1669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    res = settimeofday(tv, NULL);
1689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if (res < 0) {
1699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ALOGV("settimeofday() failed: %s\n", strerror(errno));
1709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return -1;
1719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    fd = open("/dev/rtc0", O_RDWR);
1749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if (fd < 0) {
1759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ALOGV("Unable to open RTC driver: %s\n", strerror(errno));
1769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return res;
1779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
1789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
1799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    gmtime_res = gmtime_r(&tv->tv_sec, &tm);
1803efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    if (!gmtime_res) {
1819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ALOGV("gmtime_r() failed: %s\n", strerror(errno));
1829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        res = -1;
1839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        goto done;
1843efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    }
1853efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan
1869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    memset(&rtc, 0, sizeof(rtc));
1873efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    rtc.tm_sec = tm.tm_sec;
1889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    rtc.tm_min = tm.tm_min;
1899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    rtc.tm_hour = tm.tm_hour;
1909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    rtc.tm_mday = tm.tm_mday;
1919c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    rtc.tm_mon = tm.tm_mon;
1929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    rtc.tm_year = tm.tm_year;
1939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    rtc.tm_wday = tm.tm_wday;
1949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    rtc.tm_yday = tm.tm_yday;
1958a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    rtc.tm_isdst = tm.tm_isdst;
1968a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    res = ioctl(fd, RTC_SET_TIME, &rtc);
1979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if (res < 0)
1988a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
1998a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyandone:
2008a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    close(fd);
2019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    return res;
2029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
2039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanint AlarmImplTimerFd::waitForAlarm()
2059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
2069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    epoll_event events[N_ANDROID_TIMERFDS];
2078a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan
2089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int nevents = epoll_wait(epollfd, events, N_ANDROID_TIMERFDS, -1);
2099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if (nevents < 0) {
2109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return nevents;
2119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
2129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int result = 0;
2149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    for (int i = 0; i < nevents; i++) {
2159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        uint32_t alarm_idx = events[i].data.u32;
2169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        uint64_t unused;
2179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ssize_t err = read(fds[alarm_idx], &unused, sizeof(unused));
2189c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (err < 0) {
2199c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            if (alarm_idx == ANDROID_ALARM_TYPE_COUNT && errno == ECANCELED) {
2209c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                result |= ANDROID_ALARM_TIME_CHANGE_MASK;
2219c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            } else {
2229c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                return err;
2239c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            }
2249c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        } else {
2259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            result |= (1 << alarm_idx);
2269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
2279c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
2289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    return result;
2309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
2319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanstatic jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
2339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
2349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
2359c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    struct timeval tv;
2369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int ret;
237cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg
238cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg    if (millis <= 0 || millis / 1000LL >= INT_MAX) {
2392e45c0b8f84172a004df4e3a1f50dbf1235474ebChung-yih Wang        return -1;
240cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg    }
241cf95f3b0500ae6f8e4965a05fa72b17fc49eafa3Magnus Strandberg
2429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    tv.tv_sec = (time_t) (millis / 1000LL);
2439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
2449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
2469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    ret = impl->setTime(&tv);
2489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if(ret < 0) {
2509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
2519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ret = -1;
2529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
2539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    return ret;
2549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
2559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanstatic jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
2579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
2589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    struct timezone tz;
2599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    tz.tz_minuteswest = minswest;
2619c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    tz.tz_dsttime = 0;
2629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2639329db04f13480ccdff013dcc00cdb96f12a921cWink Saville    int result = settimeofday(NULL, &tz);
264e9fe79e34d2c4100cd391bcf21df8bd50d5f3228Hung-ying Tyan    if (result < 0) {
2659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno));
2669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return -1;
2679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    } else {
2689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest);
2698a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    }
2708a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan
2718a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    return 0;
2728a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan}
2738a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan
2749c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanstatic jlong init_alarm_driver()
2759c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
2769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int fd = open("/dev/alarm", O_RDWR);
2779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if (fd < 0) {
2788a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan        ALOGV("opening alarm driver failed: %s", strerror(errno));
2799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return 0;
2809c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
2819c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2828a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    AlarmImpl *ret = new AlarmImplAlarmDriver(fd);
2838a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    return reinterpret_cast<jlong>(ret);
2848a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan}
2858a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan
2868a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyanstatic jlong init_timerfd()
2879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
288f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync    int epollfd;
289f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync    int fds[N_ANDROID_TIMERFDS];
2909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2918a044dee1690c3dc7b5f467461ce4fa65c565a66Hung-ying Tyan    epollfd = epoll_create(N_ANDROID_TIMERFDS);
292f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync    if (epollfd < 0) {
293f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync        ALOGV("epoll_create(%u) failed: %s", N_ANDROID_TIMERFDS,
294f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync                strerror(errno));
295f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync        return 0;
296f0af349a5b7b7df47e6b1b53e028cecdff50caa6repo sync    }
2979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
2989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
2999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        fds[i] = timerfd_create(android_alarm_to_clockid[i], 0);
3009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        if (fds[i] < 0) {
3019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            ALOGV("timerfd_create(%u) failed: %s",  android_alarm_to_clockid[i],
3029329db04f13480ccdff013dcc00cdb96f12a921cWink Saville                    strerror(errno));
3039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            close(epollfd);
3049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            for (size_t j = 0; j < i; j++) {
3059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                close(fds[j]);
3069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            }
3079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            return 0;
3089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        }
3099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3119c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    AlarmImpl *ret = new AlarmImplTimerFd(fds, epollfd);
3129c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3139c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    for (size_t i = 0; i < N_ANDROID_TIMERFDS; i++) {
3149c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        epoll_event event;
3159c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        event.events = EPOLLIN | EPOLLWAKEUP;
3169c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        event.data.u32 = i;
3179c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
318a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang        int err = epoll_ctl(epollfd, EPOLL_CTL_ADD, fds[i], &event);
319a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang        if (err < 0) {
320a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            ALOGV("epoll_ctl(EPOLL_CTL_ADD) failed: %s", strerror(errno));
321a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            delete ret;
322a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang            return 0;
323a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang        }
324a6d2f402722e65536628b161f07534b5e886882aChung-yih Wang    }
3259c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3269c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    struct itimerspec spec;
3279329db04f13480ccdff013dcc00cdb96f12a921cWink Saville    memset(&spec, 0, sizeof(spec));
3289c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    /* 0 = disarmed; the timerfd doesn't need to be armed to get
3299c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan       RTC change notifications, just set up as cancelable */
3309c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3319c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int err = timerfd_settime(fds[ANDROID_ALARM_TYPE_COUNT],
3329c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan            TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL);
3339c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if (err < 0) {
3349c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ALOGV("timerfd_settime() failed: %s", strerror(errno));
33522ecc3df834674605daf86f7edf20169b6ca800brepo sync        delete ret;
3369c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return 0;
3379c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3389c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3399c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    return reinterpret_cast<jlong>(ret);
3409c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
3419c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3429c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanstatic jlong android_server_AlarmManagerService_init(JNIEnv*, jobject)
3439c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
3449c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    jlong ret = init_alarm_driver();
3459c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if (ret) {
3469c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return ret;
3479c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3489c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3499c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    return init_timerfd();
3509c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
3519c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3529c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanstatic void android_server_AlarmManagerService_close(JNIEnv*, jobject, jlong nativeData)
3539c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
3549c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
3559c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    delete impl;
3569c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
3579c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3589c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanstatic void android_server_AlarmManagerService_set(JNIEnv*, jobject, jlong nativeData, jint type, jlong seconds, jlong nanoseconds)
3599c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
3609c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
3619329db04f13480ccdff013dcc00cdb96f12a921cWink Saville    struct timespec ts;
3629c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    ts.tv_sec = seconds;
3639c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    ts.tv_nsec = nanoseconds;
3649c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3659c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int result = impl->set(type, &ts);
3669c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if (result < 0)
3679c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    {
3689c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ALOGE("Unable to set alarm to %lld.%09lld: %s\n",
3699c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan              static_cast<long long>(seconds),
3709c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan              static_cast<long long>(nanoseconds), strerror(errno));
3719c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3729c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
3739c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3743efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyanstatic jint android_server_AlarmManagerService_waitForAlarm(JNIEnv*, jobject, jlong nativeData)
3753efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan{
3769c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
3779c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    int result = 0;
3789c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3799c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    do
3803efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan    {
3813efff6c5840a99faadc3ee6197940c3290f65a62Hung-ying Tyan        result = impl->waitForAlarm();
3829c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    } while (result < 0 && errno == EINTR);
3839c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3849c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    if (result < 0)
3859c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    {
3869c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        ALOGE("Unable to wait on alarm: %s\n", strerror(errno));
3879c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan        return 0;
3889c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    }
3899c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3909c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    return result;
3919329db04f13480ccdff013dcc00cdb96f12a921cWink Saville}
3929c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
3939c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanstatic JNINativeMethod sMethods[] = {
3949c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan     /* name, signature, funcPtr */
3959c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    {"init", "()J", (void*)android_server_AlarmManagerService_init},
3969c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    {"close", "(J)V", (void*)android_server_AlarmManagerService_close},
3979c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    {"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
3989c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    {"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
3999c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    {"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},
4009c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    {"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
4019c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan};
4029c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4039c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyanint register_android_server_AlarmManagerService(JNIEnv* env)
4049c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan{
4059c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan    return jniRegisterNativeMethods(env, "com/android/server/AlarmManagerService",
4069c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan                                    sMethods, NELEM(sMethods));
4079c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan}
4089c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan
4099c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan} /* namespace android */
4109c1fbe7bca34ac7463079926a401a3ce42717460Hung-ying Tyan