Use POSIX timer for non-wake alarms in bluedroid.

After this change, bluedroid will go through AlarmManager for wake
alarms (>= 3s) and POSIX timers + wake lock for short deadlines.
This change allows A2DP to continue streaming while the screen is
off.

Change-Id: I56622a6873aa431842dd1d97e830849ac2fe6773
diff --git a/gki/ulinux/gki_ulinux.c b/gki/ulinux/gki_ulinux.c
index 6c7182d..256a5ae 100644
--- a/gki/ulinux/gki_ulinux.c
+++ b/gki/ulinux/gki_ulinux.c
@@ -87,6 +87,9 @@
 // NOTE: Must be manipulated with the GKI_disable() lock held.
 static alarm_service_t alarm_service;
 
+static timer_t posix_timer;
+static bool timer_created;
+
 // If the next wakeup time is less than this threshold, we should acquire
 // a wakelock instead of setting a wake alarm so we're not bouncing in
 // and out of suspend frequently.
@@ -106,10 +109,32 @@
 **  Functions
 ******************************************************************************/
 
+static bool set_nonwake_alarm(uint64_t delay_millis) {
+  if (!timer_created) {
+    ALOGE("%s timer is not available, not setting timer for %llums", __func__, delay_millis);
+    return false;
+  }
+
+  struct timeval tv;
+  gettimeofday(&tv, NULL);
+
+  uint64_t millis = (tv.tv_sec * 1000LL) + (tv.tv_usec / 1000LL) + delay_millis;
+
+  struct itimerspec new_value;
+  memset(&new_value, 0, sizeof(new_value));
+  new_value.it_value.tv_sec = (millis / 1000);
+  new_value.it_value.tv_nsec = (millis % 1000) * 1000000LL;
+  if (timer_settime(posix_timer, TIMER_ABSTIME, &new_value, NULL) == -1) {
+    ALOGE("%s unable to set timer: %s", __func__, strerror(errno));
+    return false;
+  }
+
+  return true;
+}
+
 /** Callback from Java thread after alarm from AlarmService fires. */
 static void bt_alarm_cb(void *data) {
-    alarm_service_t *alarm_service = (alarm_service_t *)data;
-    GKI_timer_update(alarm_service->num_ticks);
+    GKI_timer_update(alarm_service.num_ticks);
 }
 
 /** NOTE: This is only called on init and may be called without the GKI_disable()
@@ -161,7 +186,7 @@
         }
         alarm_service.wakelock = true;
         ALOGV("%s acquired wake lock, setting short alarm (%lldms).", __func__, ticks_in_millis);
-        if (!bt_os_callouts->set_wake_alarm(ticks_in_millis, false, bt_alarm_cb, &alarm_service)) {
+        if (!set_nonwake_alarm(ticks_in_millis)) {
             ALOGE("%s unable to set short alarm.", __func__);
         }
     } else {
@@ -243,6 +268,17 @@
     /* pthread_mutex_init(&thread_delay_mutex, NULL); */  /* used in GKI_delay */
     /* pthread_cond_init (&thread_delay_cond, NULL); */
 
+    struct sigevent sigevent;
+    memset(&sigevent, 0, sizeof(sigevent));
+    sigevent.sigev_notify = SIGEV_THREAD;
+    sigevent.sigev_notify_function = (void (*)(union sigval))bt_alarm_cb;
+    sigevent.sigev_value.sival_ptr = NULL;
+    if (timer_create(CLOCK_REALTIME, &sigevent, &posix_timer) == -1) {
+        ALOGE("%s unable to create POSIX timer: %s", __func__, strerror(errno));
+        timer_created = false;
+    } else {
+        timer_created = true;
+    }
 }
 
 
@@ -564,6 +600,10 @@
     i = 0;
 #endif
 
+    if (timer_created) {
+        timer_delete(posix_timer);
+        timer_created = false;
+    }
 }
 
 /*****************************************************************************