am 6801cedb: am 6a3e7dfa: am c738783c: Merge "Fix alarms with negative or very large wakup times." into froyo
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 @@
     }
     
     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 @@
     {
         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 @@
     
     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 @@
 #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 @@
      /* 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},
 };