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 */
|
||||
void set(int type, long triggerAtTime, long windowLength,
|
||||
long interval, in PendingIntent operation, in WorkSource workSource);
|
||||
void setTime(long millis);
|
||||
boolean setTime(long millis);
|
||||
void setTimeZone(String zone);
|
||||
void remove(in PendingIntent operation);
|
||||
}
|
||||
|
@ -16,6 +16,9 @@
|
||||
|
||||
package android.os;
|
||||
|
||||
import android.app.IAlarmManager;
|
||||
import android.content.Context;
|
||||
import android.util.Slog;
|
||||
|
||||
/**
|
||||
* Core timekeeping facilities.
|
||||
@ -89,6 +92,8 @@ package android.os;
|
||||
* </ul>
|
||||
*/
|
||||
public final class SystemClock {
|
||||
private static final String TAG = "SystemClock";
|
||||
|
||||
/**
|
||||
* This class is uninstantiable.
|
||||
*/
|
||||
@ -134,7 +139,23 @@ public final class SystemClock {
|
||||
*
|
||||
* @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.
|
||||
|
@ -19,13 +19,6 @@
|
||||
* 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 <limits.h>
|
||||
#include <fcntl.h>
|
||||
@ -43,109 +36,6 @@
|
||||
|
||||
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();
|
||||
*/
|
||||
@ -230,8 +120,6 @@ static jlong android_os_SystemClock_elapsedRealtimeNano(JNIEnv* env,
|
||||
*/
|
||||
static JNINativeMethod gMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{ "setCurrentTimeMillis", "(J)Z",
|
||||
(void*) android_os_SystemClock_setCurrentTimeMillis },
|
||||
{ "uptimeMillis", "()J",
|
||||
(void*) android_os_SystemClock_uptimeMillis },
|
||||
{ "elapsedRealtime", "()J",
|
||||
|
@ -669,12 +669,19 @@ class AlarmManagerService extends IAlarmManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
public void setTime(long millis) {
|
||||
public boolean setTime(long millis) {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
"android.permission.SET_TIME",
|
||||
"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) {
|
||||
@ -1018,6 +1025,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
|
||||
private native void close(long nativeData);
|
||||
private native void set(long nativeData, int type, long seconds, long nanoseconds);
|
||||
private native int waitForAlarm(long nativeData);
|
||||
private native int setKernelTime(long nativeData, long millis);
|
||||
private native int setKernelTimezone(long nativeData, int minuteswest);
|
||||
|
||||
private void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) {
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <unistd.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/android_alarm.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
@ -58,6 +59,7 @@ public:
|
||||
virtual ~AlarmImpl();
|
||||
|
||||
virtual int set(int type, struct timespec *ts) = 0;
|
||||
virtual int setTime(struct timeval *tv) = 0;
|
||||
virtual int waitForAlarm() = 0;
|
||||
|
||||
protected:
|
||||
@ -71,6 +73,7 @@ public:
|
||||
AlarmImplAlarmDriver(int fd) : AlarmImpl(&fd, 1) { }
|
||||
|
||||
int set(int type, struct timespec *ts);
|
||||
int setTime(struct timeval *tv);
|
||||
int waitForAlarm();
|
||||
};
|
||||
|
||||
@ -82,6 +85,7 @@ public:
|
||||
~AlarmImplTimerFd();
|
||||
|
||||
int set(int type, struct timespec *ts);
|
||||
int setTime(struct timeval *tv);
|
||||
int waitForAlarm();
|
||||
|
||||
private:
|
||||
@ -107,6 +111,19 @@ 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);
|
||||
@ -140,6 +157,50 @@ int AlarmImplTimerFd::set(int type, struct timespec *ts)
|
||||
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()
|
||||
{
|
||||
epoll_event events[N_ANDROID_TIMERFDS];
|
||||
@ -168,6 +229,30 @@ int AlarmImplTimerFd::waitForAlarm()
|
||||
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)
|
||||
{
|
||||
struct timezone tz;
|
||||
@ -309,6 +394,7 @@ static JNINativeMethod sMethods[] = {
|
||||
{"close", "(J)V", (void*)android_server_AlarmManagerService_close},
|
||||
{"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},
|
||||
{"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},
|
||||
{"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},
|
||||
{"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user