summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Hackmann <ghackmann@google.com>2014-02-21 21:01:00 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-02-21 21:01:00 +0000
commitbbfc08b3abc0934f67659f3238eb79dcac838c17 (patch)
treeeea336e87470e51d017700e56ff54e275d51592c
parent4a80927241b3168d9d5138c46c22385d6467a736 (diff)
parentc9244720da829cac94918555761468ebdd2b7c5d (diff)
downloadframeworks_base-bbfc08b3abc0934f67659f3238eb79dcac838c17.zip
frameworks_base-bbfc08b3abc0934f67659f3238eb79dcac838c17.tar.gz
frameworks_base-bbfc08b3abc0934f67659f3238eb79dcac838c17.tar.bz2
Merge changes I6d4fdada,Ia34899a4
* changes: open("/dev/rtc0") failure in AlarmManagerService.setTime() should be non-fatal Move time setting code from SystemClock to AlarmManagerService
-rw-r--r--core/java/android/app/IAlarmManager.aidl2
-rw-r--r--core/java/android/os/SystemClock.java23
-rw-r--r--core/jni/android_os_SystemClock.cpp112
-rw-r--r--services/java/com/android/server/AlarmManagerService.java12
-rw-r--r--services/jni/com_android_server_AlarmManagerService.cpp86
5 files changed, 119 insertions, 116 deletions
diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl
index 8476609..ef9f26e 100644
--- a/core/java/android/app/IAlarmManager.aidl
+++ b/core/java/android/app/IAlarmManager.aidl
@@ -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);
}
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index 729c64b..672df6d 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -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.
diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp
index 5f4d570..6247844 100644
--- a/core/jni/android_os_SystemClock.cpp
+++ b/core/jni/android_os_SystemClock.cpp
@@ -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",
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 2e1b0af..defc6ef 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -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) {
diff --git a/services/jni/com_android_server_AlarmManagerService.cpp b/services/jni/com_android_server_AlarmManagerService.cpp
index 342515b..c26a516 100644
--- a/services/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/jni/com_android_server_AlarmManagerService.cpp
@@ -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},
};