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:
Greg Hackmann
2014-02-21 13:04:00 -08:00
committed by Android Git Automerger
5 changed files with 119 additions and 116 deletions

View File

@ -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);
}

View File

@ -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.

View File

@ -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",

View File

@ -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) {

View File

@ -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},
};