summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2010-03-31 15:29:40 -0700
committerJeff Brown <jeffbrown@google.com>2010-03-31 15:38:08 -0700
commit11c5f1a65d6c495cc60f9f15d408c776baed9f73 (patch)
tree1a82c873340eabb636e04091c0fd59be3b271984
parent966fcb81eece9096040ccc185bb662335d3964cf (diff)
downloadframeworks_base-11c5f1a65d6c495cc60f9f15d408c776baed9f73.zip
frameworks_base-11c5f1a65d6c495cc60f9f15d408c776baed9f73.tar.gz
frameworks_base-11c5f1a65d6c495cc60f9f15d408c776baed9f73.tar.bz2
Fix alarms with negative or very large wakup times.
When the wakeup time is negative, the kernel /dev/alarm driver never triggers the alarm. This can cause alarms to back up in the priority queue since an alarm at the head with a negative wakup time will never be triggered. Now we use 0 as the wakup time which causes an immediate triggering. When the wakeup time is very large, it is possible for a numeric overflow to occur when converting the timestamp from milliseconds since epoch to nanoseconds. This has been fixed by avoiding the intermediate conversion in the JNI call so that overflow cannot occur. Bug: b/2558820 Change-Id: I4f5b4646a04090cc749a9fc5d3982a68402954ef
-rw-r--r--services/java/com/android/server/AlarmManagerService.java17
-rw-r--r--services/jni/com_android_server_AlarmManagerService.cpp14
2 files changed, 19 insertions, 12 deletions
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 1ffb427..e088417 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -400,7 +400,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
}
public long timeToNextAlarm() {
- long nextAlarm = 0xfffffffffffffffl;
+ long nextAlarm = Long.MAX_VALUE;
synchronized (mLock) {
for (int i=AlarmManager.RTC_WAKEUP;
i<=AlarmManager.ELAPSED_REALTIME; i++) {
@@ -420,7 +420,18 @@ class AlarmManagerService extends IAlarmManager.Stub {
{
if (mDescriptor != -1)
{
- set(mDescriptor, alarm.type, (alarm.when * 1000 * 1000));
+ // The kernel never triggers alarms with negative wakeup times
+ // so we ensure they are positive.
+ long alarmSeconds, alarmNanoseconds;
+ if (alarm.when < 0) {
+ alarmSeconds = 0;
+ alarmNanoseconds = 0;
+ } else {
+ alarmSeconds = alarm.when / 1000;
+ alarmNanoseconds = (alarm.when % 1000) * 1000 * 1000;
+ }
+
+ set(mDescriptor, alarm.type, alarmSeconds, alarmNanoseconds);
}
else
{
@@ -499,7 +510,7 @@ class AlarmManagerService extends IAlarmManager.Stub {
private native int init();
private native void close(int fd);
- private native void set(int fd, int type, long nanoseconds);
+ private native void set(int fd, int type, long seconds, long nanoseconds);
private native int waitForAlarm(int fd);
private native int setKernelTimezone(int fd, int minuteswest);
diff --git a/services/jni/com_android_server_AlarmManagerService.cpp b/services/jni/com_android_server_AlarmManagerService.cpp
index 85d63c9..0e162bd 100644
--- a/services/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/jni/com_android_server_AlarmManagerService.cpp
@@ -38,10 +38,6 @@
#include <linux/android_alarm.h>
#endif
-#define ONE_NANOSECOND 1000000000LL
-#define NANOSECONDS_TO_SECONDS(x) (x / ONE_NANOSECOND)
-#define SECONDS_TO_NANOSECONDS(x) (x * ONE_NANOSECOND)
-
namespace android {
static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv* env, jobject obj, jint fd, jint minswest)
@@ -82,17 +78,17 @@ static void android_server_AlarmManagerService_close(JNIEnv* env, jobject obj, j
#endif
}
-static void android_server_AlarmManagerService_set(JNIEnv* env, jobject obj, jint fd, jint type, jlong nanoseconds)
+static void android_server_AlarmManagerService_set(JNIEnv* env, jobject obj, jint fd, jint type, jlong seconds, jlong nanoseconds)
{
#if HAVE_ANDROID_OS
struct timespec ts;
- ts.tv_sec = NANOSECONDS_TO_SECONDS(nanoseconds);
- ts.tv_nsec = nanoseconds - SECONDS_TO_NANOSECONDS(ts.tv_sec);
+ ts.tv_sec = seconds;
+ ts.tv_nsec = nanoseconds;
int result = ioctl(fd, ANDROID_ALARM_SET(type), &ts);
if (result < 0)
{
- LOGE("Unable to set alarm to %lld: %s\n", nanoseconds, strerror(errno));
+ LOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno));
}
#endif
}
@@ -121,7 +117,7 @@ static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"init", "()I", (void*)android_server_AlarmManagerService_init},
{"close", "(I)V", (void*)android_server_AlarmManagerService_close},
- {"set", "(IIJ)V", (void*)android_server_AlarmManagerService_set},
+ {"set", "(IIJJ)V", (void*)android_server_AlarmManagerService_set},
{"waitForAlarm", "(I)I", (void*)android_server_AlarmManagerService_waitForAlarm},
{"setKernelTimezone", "(II)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
};