am bbfc08b3
: Merge changes I6d4fdada,Ia34899a4
* commit 'bbfc08b3abc0934f67659f3238eb79dcac838c17': open("/dev/rtc0") failure in AlarmManagerService.setTime() should be non-fatal Move time setting code from SystemClock to AlarmManagerService
This commit is contained in:
@ -28,7 +28,7 @@ interface IAlarmManager {
|
|||||||
/** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */
|
/** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */
|
||||||
void set(int type, long triggerAtTime, long windowLength,
|
void set(int type, long triggerAtTime, long windowLength,
|
||||||
long interval, in PendingIntent operation, in WorkSource workSource);
|
long interval, in PendingIntent operation, in WorkSource workSource);
|
||||||
void setTime(long millis);
|
boolean setTime(long millis);
|
||||||
void setTimeZone(String zone);
|
void setTimeZone(String zone);
|
||||||
void remove(in PendingIntent operation);
|
void remove(in PendingIntent operation);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package android.os;
|
package android.os;
|
||||||
|
|
||||||
|
import android.app.IAlarmManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Slog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Core timekeeping facilities.
|
* Core timekeeping facilities.
|
||||||
@ -89,6 +92,8 @@ package android.os;
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public final class SystemClock {
|
public final class SystemClock {
|
||||||
|
private static final String TAG = "SystemClock";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is uninstantiable.
|
* This class is uninstantiable.
|
||||||
*/
|
*/
|
||||||
@ -134,7 +139,23 @@ public final class SystemClock {
|
|||||||
*
|
*
|
||||||
* @return if the clock was successfully set to the specified time.
|
* @return if the clock was successfully set to the specified time.
|
||||||
*/
|
*/
|
||||||
native public static boolean setCurrentTimeMillis(long millis);
|
public static boolean setCurrentTimeMillis(long millis) {
|
||||||
|
IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
|
||||||
|
IAlarmManager mgr = IAlarmManager.Stub.asInterface(b);
|
||||||
|
if (mgr == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return mgr.setTime(millis);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "Unable to set RTC", e);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
Slog.e(TAG, "Unable to set RTC", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns milliseconds since boot, not counting time spent in deep sleep.
|
* Returns milliseconds since boot, not counting time spent in deep sleep.
|
||||||
|
@ -19,13 +19,6 @@
|
|||||||
* System clock functions.
|
* System clock functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_ANDROID_OS
|
|
||||||
#include <linux/ioctl.h>
|
|
||||||
#include <linux/rtc.h>
|
|
||||||
#include <utils/Atomic.h>
|
|
||||||
#include <linux/android_alarm.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -43,109 +36,6 @@
|
|||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
static int setCurrentTimeMillisAlarmDriver(struct timeval *tv)
|
|
||||||
{
|
|
||||||
struct timespec ts;
|
|
||||||
int fd;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
fd = open("/dev/alarm", O_RDWR);
|
|
||||||
if(fd < 0) {
|
|
||||||
ALOGV("Unable to open alarm driver: %s\n", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ts.tv_sec = tv->tv_sec;
|
|
||||||
ts.tv_nsec = tv->tv_usec * 1000;
|
|
||||||
res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
|
|
||||||
if (res < 0)
|
|
||||||
ALOGV("ANDROID_ALARM_SET_RTC ioctl failed: %s\n", strerror(errno));
|
|
||||||
close(fd);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int setCurrentTimeMillisRtc(struct timeval *tv)
|
|
||||||
{
|
|
||||||
struct rtc_time rtc;
|
|
||||||
struct tm tm, *gmtime_res;
|
|
||||||
int fd;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
fd = open("/dev/rtc0", O_RDWR);
|
|
||||||
if (fd < 0) {
|
|
||||||
ALOGV("Unable to open RTC driver: %s\n", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = settimeofday(tv, NULL);
|
|
||||||
if (res < 0) {
|
|
||||||
ALOGV("settimeofday() failed: %s\n", strerror(errno));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
gmtime_res = gmtime_r(&tv->tv_sec, &tm);
|
|
||||||
if (!gmtime_res) {
|
|
||||||
ALOGV("gmtime_r() failed: %s\n", strerror(errno));
|
|
||||||
res = -1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&rtc, 0, sizeof(rtc));
|
|
||||||
rtc.tm_sec = tm.tm_sec;
|
|
||||||
rtc.tm_min = tm.tm_min;
|
|
||||||
rtc.tm_hour = tm.tm_hour;
|
|
||||||
rtc.tm_mday = tm.tm_mday;
|
|
||||||
rtc.tm_mon = tm.tm_mon;
|
|
||||||
rtc.tm_year = tm.tm_year;
|
|
||||||
rtc.tm_wday = tm.tm_wday;
|
|
||||||
rtc.tm_yday = tm.tm_yday;
|
|
||||||
rtc.tm_isdst = tm.tm_isdst;
|
|
||||||
res = ioctl(fd, RTC_SET_TIME, &rtc);
|
|
||||||
if (res < 0)
|
|
||||||
ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
|
|
||||||
done:
|
|
||||||
close(fd);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the current time. This only works when running as root.
|
|
||||||
*/
|
|
||||||
static int setCurrentTimeMillis(int64_t millis)
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (millis <= 0 || millis / 1000LL >= INT_MAX) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tv.tv_sec = (time_t) (millis / 1000LL);
|
|
||||||
tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
|
|
||||||
|
|
||||||
ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
|
|
||||||
|
|
||||||
ret = setCurrentTimeMillisAlarmDriver(&tv);
|
|
||||||
if (ret < 0)
|
|
||||||
ret = setCurrentTimeMillisRtc(&tv);
|
|
||||||
|
|
||||||
if(ret < 0) {
|
|
||||||
ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* native public static void setCurrentTimeMillis(long millis)
|
|
||||||
*
|
|
||||||
* Set the current time. This only works when running as root.
|
|
||||||
*/
|
|
||||||
static jboolean android_os_SystemClock_setCurrentTimeMillis(JNIEnv* env,
|
|
||||||
jobject clazz, jlong millis)
|
|
||||||
{
|
|
||||||
return (setCurrentTimeMillis(millis) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* native public static long uptimeMillis();
|
* native public static long uptimeMillis();
|
||||||
*/
|
*/
|
||||||
@ -230,8 +120,6 @@ static jlong android_os_SystemClock_elapsedRealtimeNano(JNIEnv* env,
|
|||||||
*/
|
*/
|
||||||
static JNINativeMethod gMethods[] = {
|
static JNINativeMethod gMethods[] = {
|
||||||
/* name, signature, funcPtr */
|
/* name, signature, funcPtr */
|
||||||
{ "setCurrentTimeMillis", "(J)Z",
|
|
||||||
(void*) android_os_SystemClock_setCurrentTimeMillis },
|
|
||||||
{ "uptimeMillis", "()J",
|
{ "uptimeMillis", "()J",
|
||||||
(void*) android_os_SystemClock_uptimeMillis },
|
(void*) android_os_SystemClock_uptimeMillis },
|
||||||
{ "elapsedRealtime", "()J",
|
{ "elapsedRealtime", "()J",
|
||||||
|
@ -669,12 +669,19 @@ class AlarmManagerService extends IAlarmManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTime(long millis) {
|
public boolean setTime(long millis) {
|
||||||
mContext.enforceCallingOrSelfPermission(
|
mContext.enforceCallingOrSelfPermission(
|
||||||
"android.permission.SET_TIME",
|
"android.permission.SET_TIME",
|
||||||
"setTime");
|
"setTime");
|
||||||
|
|
||||||
SystemClock.setCurrentTimeMillis(millis);
|
if (mNativeData == 0) {
|
||||||
|
Slog.w(TAG, "Not setting time since no alarm driver is available.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (mLock) {
|
||||||
|
return setKernelTime(mNativeData, millis) == 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTimeZone(String tz) {
|
public void setTimeZone(String tz) {
|
||||||
@ -1018,6 +1025,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
|
|||||||
private native void close(long nativeData);
|
private native void close(long nativeData);
|
||||||
private native void set(long nativeData, int type, long seconds, long nanoseconds);
|
private native void set(long nativeData, int type, long seconds, long nanoseconds);
|
||||||
private native int waitForAlarm(long nativeData);
|
private native int waitForAlarm(long nativeData);
|
||||||
|
private native int setKernelTime(long nativeData, long millis);
|
||||||
private native int setKernelTimezone(long nativeData, int minuteswest);
|
private native int setKernelTimezone(long nativeData, int minuteswest);
|
||||||
|
|
||||||
private void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) {
|
private void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) {
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <linux/ioctl.h>
|
#include <linux/ioctl.h>
|
||||||
#include <linux/android_alarm.h>
|
#include <linux/android_alarm.h>
|
||||||
|
#include <linux/rtc.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ public:
|
|||||||
virtual ~AlarmImpl();
|
virtual ~AlarmImpl();
|
||||||
|
|
||||||
virtual int set(int type, struct timespec *ts) = 0;
|
virtual int set(int type, struct timespec *ts) = 0;
|
||||||
|
virtual int setTime(struct timeval *tv) = 0;
|
||||||
virtual int waitForAlarm() = 0;
|
virtual int waitForAlarm() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -71,6 +73,7 @@ public:
|
|||||||
AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }
|
AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }
|
||||||
|
|
||||||
int set(int type, struct timespec *ts);
|
int set(int type, struct timespec *ts);
|
||||||
|
int setTime(struct timeval *tv);
|
||||||
int waitForAlarm();
|
int waitForAlarm();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -82,6 +85,7 @@ public:
|
|||||||
~AlarmImplTimerFd();
|
~AlarmImplTimerFd();
|
||||||
|
|
||||||
int set(int type, struct timespec *ts);
|
int set(int type, struct timespec *ts);
|
||||||
|
int setTime(struct timeval *tv);
|
||||||
int waitForAlarm();
|
int waitForAlarm();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -107,6 +111,19 @@ int AlarmImplAlarmDriver::set(int type, struct timespec *ts)
|
|||||||
return ioctl(fds[0], ANDROID_ALARM_SET(type), 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()
|
int AlarmImplAlarmDriver::waitForAlarm()
|
||||||
{
|
{
|
||||||
return ioctl(fds[0], ANDROID_ALARM_WAIT);
|
return ioctl(fds[0], ANDROID_ALARM_WAIT);
|
||||||
@ -140,6 +157,50 @@ int AlarmImplTimerFd::set(int type, struct timespec *ts)
|
|||||||
return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
|
return timerfd_settime(fds[type], TFD_TIMER_ABSTIME, &spec, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AlarmImplTimerFd::setTime(struct timeval *tv)
|
||||||
|
{
|
||||||
|
struct rtc_time rtc;
|
||||||
|
struct tm tm, *gmtime_res;
|
||||||
|
int fd;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = settimeofday(tv, NULL);
|
||||||
|
if (res < 0) {
|
||||||
|
ALOGV("settimeofday() failed: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open("/dev/rtc0", O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
ALOGV("Unable to open RTC driver: %s\n", strerror(errno));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
gmtime_res = gmtime_r(&tv->tv_sec, &tm);
|
||||||
|
if (!gmtime_res) {
|
||||||
|
ALOGV("gmtime_r() failed: %s\n", strerror(errno));
|
||||||
|
res = -1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&rtc, 0, sizeof(rtc));
|
||||||
|
rtc.tm_sec = tm.tm_sec;
|
||||||
|
rtc.tm_min = tm.tm_min;
|
||||||
|
rtc.tm_hour = tm.tm_hour;
|
||||||
|
rtc.tm_mday = tm.tm_mday;
|
||||||
|
rtc.tm_mon = tm.tm_mon;
|
||||||
|
rtc.tm_year = tm.tm_year;
|
||||||
|
rtc.tm_wday = tm.tm_wday;
|
||||||
|
rtc.tm_yday = tm.tm_yday;
|
||||||
|
rtc.tm_isdst = tm.tm_isdst;
|
||||||
|
res = ioctl(fd, RTC_SET_TIME, &rtc);
|
||||||
|
if (res < 0)
|
||||||
|
ALOGV("RTC_SET_TIME ioctl failed: %s\n", strerror(errno));
|
||||||
|
done:
|
||||||
|
close(fd);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
int AlarmImplTimerFd::waitForAlarm()
|
int AlarmImplTimerFd::waitForAlarm()
|
||||||
{
|
{
|
||||||
epoll_event events[N_ANDROID_TIMERFDS];
|
epoll_event events[N_ANDROID_TIMERFDS];
|
||||||
@ -168,6 +229,30 @@ int AlarmImplTimerFd::waitForAlarm()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
|
||||||
|
{
|
||||||
|
AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
|
||||||
|
struct timeval tv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (millis <= 0 || millis / 1000LL >= INT_MAX) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tv.tv_sec = (time_t) (millis / 1000LL);
|
||||||
|
tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
|
||||||
|
|
||||||
|
ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
|
||||||
|
|
||||||
|
ret = impl->setTime(&tv);
|
||||||
|
|
||||||
|
if(ret < 0) {
|
||||||
|
ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
|
static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
|
||||||
{
|
{
|
||||||
struct timezone tz;
|
struct timezone tz;
|
||||||
@ -309,6 +394,7 @@ static JNINativeMethod sMethods[] = {
|
|||||||
{"close", "(J)V", (void*)android_server_AlarmManagerService_close},
|
{"close", "(J)V", (void*)android_server_AlarmManagerService_close},
|
||||||
{"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
|
{"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
|
||||||
{"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
|
{"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
|
||||||
|
{"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},
|
||||||
{"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
|
{"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user