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