Add timerfd backend to AlarmManagerService

On devices without /dev/alarm, use a new backend based on timerfd.
timerfd has near-equivalent syscalls for the /dev/alarm ioctls we care
about, with two key differences:

1) /dev/alarm uses one fd for all clocks, while timerfd needs one fd per
clock type.

AlarmManagerService addresses this by replacing the fd (int) with an
opaque pointer (long) to the backend-specific state.

2) When the RTC changes, the /dev/alarm WAIT ioctl always returns, while
timerfd cancels (and signals events) only on specially-flagged RTC
timerfds.

The timerfd backend masks this by creating an extraneous RTC timerfd,
specifically so there's always something to signal on RTC changes.

Change-Id: I5aef867748298610347f6e1479dd8bf569495832
Signed-off-by: Greg Hackmann <ghackmann@google.com>
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 5ae9a6d..2e1b0af 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -99,7 +99,7 @@
 
     private Object mLock = new Object();
 
-    private int mDescriptor;
+    private long mNativeData;
     private long mNextWakeup;
     private long mNextNonWakeup;
     private int mBroadcastRefCount = 0;
@@ -464,7 +464,7 @@
     
     public AlarmManagerService(Context context) {
         mContext = context;
-        mDescriptor = init();
+        mNativeData = init();
         mNextWakeup = mNextNonWakeup = 0;
 
         // We have to set current TimeZone info to kernel
@@ -493,7 +493,7 @@
         mClockReceiver.scheduleDateChangedEvent();
         mUninstallReceiver = new UninstallReceiver();
         
-        if (mDescriptor != -1) {
+        if (mNativeData != 0) {
             mWaitThread.start();
         } else {
             Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
@@ -502,7 +502,7 @@
     
     protected void finalize() throws Throwable {
         try {
-            close(mDescriptor);
+            close(mNativeData);
         } finally {
             super.finalize();
         }
@@ -702,7 +702,7 @@
                 // Update the kernel timezone information
                 // Kernel tracks time offsets as 'minutes west of GMT'
                 int gmtOffset = zone.getOffset(System.currentTimeMillis());
-                setKernelTimezone(mDescriptor, -(gmtOffset / 60000));
+                setKernelTimezone(mNativeData, -(gmtOffset / 60000));
             }
 
             TimeZone.setDefault(null);
@@ -796,7 +796,7 @@
 
     private void setLocked(int type, long when)
     {
-        if (mDescriptor != -1)
+        if (mNativeData != 0)
         {
             // The kernel never triggers alarms with negative wakeup times
             // so we ensure they are positive.
@@ -809,7 +809,7 @@
                 alarmNanoseconds = (when % 1000) * 1000 * 1000;
             }
             
-            set(mDescriptor, type, alarmSeconds, alarmNanoseconds);
+            set(mNativeData, type, alarmSeconds, alarmNanoseconds);
         }
         else
         {
@@ -1014,11 +1014,11 @@
         }
     }
 
-    private native int init();
-    private native void close(int fd);
-    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);
+    private native long init();
+    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 setKernelTimezone(long nativeData, int minuteswest);
 
     private void triggerAlarmsLocked(ArrayList<Alarm> triggerList, long nowELAPSED, long nowRTC) {
         // batches are temporally sorted, so we need only pull from the
@@ -1158,7 +1158,7 @@
 
             while (true)
             {
-                int result = waitForAlarm(mDescriptor);
+                int result = waitForAlarm(mNativeData);
 
                 triggerList.clear();
 
@@ -1340,7 +1340,7 @@
                 // daylight savings information.
                 TimeZone zone = TimeZone.getTimeZone(SystemProperties.get(TIMEZONE_PROPERTY));
                 int gmtOffset = zone.getOffset(System.currentTimeMillis());
-                setKernelTimezone(mDescriptor, -(gmtOffset / 60000));
+                setKernelTimezone(mNativeData, -(gmtOffset / 60000));
                 scheduleDateChangedEvent();
             }
         }