alarm.cc revision 1afbe154a89ad462de739704ce70eed0e32cbc00
131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/******************************************************************************
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *  Copyright (C) 2014 Google, Inc.
431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *  you may not use this file except in compliance with the License.
731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *  You may obtain a copy of the License at:
831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *  See the License for the specific language governing permissions and
1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *  limitations under the License.
1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
17a5902524d4403885eb4c50360bf3465c6be796efJoe Onorato ******************************************************************************/
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
198edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka#define LOG_TAG "bt_osi_alarm"
208edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka
21495f2892288504f4ab87e62957b3f71144dd73c2Adam Powell#include <assert.h>
220280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka#include <errno.h>
238edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka#include <hardware/bluetooth.h>
24b1254a6bdb11024042fb6c27e179210c1bbd6e1cChet Haase#include <inttypes.h>
250280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka#include <time.h>
260280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka#include <utils/Log.h>
27cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
28cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy#include "alarm.h"
298edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka#include "list.h"
30cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy#include "osi.h"
3168846fdce6c01bbe474bd0c8307e1ccaac161cbcWinson Chung
328f573952b8729b4319043ae0908997ecd2d68951Dianne Hackbornstruct alarm_t {
33629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy  // The lock is held while the callback for this alarm is being executed.
34629de3ef739883c0962423cc0c3a26299f162d3dRomain Guy  // It allows us to release the coarse-grained monitor lock while a potentially
35a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung  // long-running callback is executing. |alarm_cancel| uses this lock to provide
36a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung  // a guarantee to its caller that the callback will not be in progress when it
37495f2892288504f4ab87e62957b3f71144dd73c2Adam Powell  // returns.
3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  pthread_mutex_t callback_lock;
3931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  period_ms_t deadline;
40495f2892288504f4ab87e62957b3f71144dd73c2Adam Powell  alarm_callback_t callback;
415c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy  void *data;
427247f6315baf16eacb3286f21bd80321385c1defPatrick Dubroy};
4331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
444be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratoextern bt_os_callouts_t *bt_os_callouts;
456b879f0a5885274a85333531e091283405d490ccAdam Lesinski
4631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project// If the next wakeup time is less than this threshold, we should acquire
47a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka// a wakelock instead of setting a wake alarm so we're not bouncing in
48a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung// and out of suspend frequently. This value is externally visible to allow
4931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project// unit tests to run faster. It should not be modified by production code.
50a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungint64_t TIMER_INTERVAL_FOR_WAKELOCK_IN_MS = 3000;
514be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onoratostatic const clockid_t CLOCK_ID = CLOCK_BOOTTIME;
52f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectstatic const char *WAKE_LOCK_ID = "bluedroid_timer";
535c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy
54956091ba7863bd72086275e61084864994dd6fa7Joe Onorato// This mutex ensures that the |alarm_set|, |alarm_cancel|, and alarm callback
55495f2892288504f4ab87e62957b3f71144dd73c2Adam Powell// functions execute serially and not concurrently. As a result, this mutex also
5631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project// protects the |alarms| list.
57291ad12232c98e383d44d76ffe09e97e204c61bcDaniel Sandlerstatic pthread_mutex_t monitor;
58580e27748137ff08599aa719d106b31215a28353Winson Chungstatic list_t *alarms;
59a34abf8c781485b788fddacb352d586bffca886cWinson Chungstatic timer_t timer;
60a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungstatic bool timer_set;
6131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
6231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectstatic bool lazy_initialize(void);
63cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroystatic period_ms_t now(void);
64f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectstatic void timer_callback(void *data);
65a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chungstatic void reschedule(void);
6631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
678edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurkaalarm_t *alarm_new(void) {
688edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka  // Make sure we have a list we can insert alarms into.
698edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka  if (!alarms && !lazy_initialize())
70edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy    return NULL;
7131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
720142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka  pthread_mutexattr_t attr;
730142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka  pthread_mutexattr_init(&attr);
74aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
7531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  alarm_t *ret = calloc(1, sizeof(alarm_t));
760142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka  if (!ret) {
77dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    ALOGE("%s unable to allocate memory for alarm.", __func__);
78e47f55c30b9c24f01f2be861247c92f17fbe4a61Romain Guy    goto error;
793a8820bdbad90642cf5cda4b00a8c92ecb699159Joe Onorato  }
800142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
81dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka  // Make this a recursive mutex to make it safe to call |alarm_cancel| from
82dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka  // within the callback function of the alarm.
83dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka  int error = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
84a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen  if (error) {
85d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka    ALOGE("%s unable to create a recursive mutex: %s", __func__, strerror(error));
86d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka    goto error;
87d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka  }
88f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
89f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen  error = pthread_mutex_init(&ret->callback_lock, &attr);
90a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen  if (error) {
91a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    ALOGE("%s unable to initialize mutex: %s", __func__, strerror(error));
92a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen    goto error;
931b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen  }
94a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen
951b0aaac0b3abd777ed319341f95a8dfff23c79f4Adam Cohen  pthread_mutexattr_destroy(&attr);
96a985e598f6071f4caca15ba3cb6b2cd3e38b217dAdam Cohen  return ret;
9768d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen
9868d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohenerror:;
999171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung  pthread_mutexattr_destroy(&attr);
100f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen  free(ret);
101f135c6c364e92cddb84c1b4a94ed535214b712a6Winson Chung  return NULL;
1029171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung}
1039171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
1049171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chungvoid alarm_free(alarm_t *alarm) {
1059171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung  if (!alarm)
1069171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    return;
1079171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
1089171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung  alarm_cancel(alarm);
1099171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung  pthread_mutex_destroy(&alarm->callback_lock);
110472b281d5cb4f5660df981a6c912266b9f5703feChet Haase  free(alarm);
111472b281d5cb4f5660df981a6c912266b9f5703feChet Haase}
1129171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung
1138d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung// Runs in exclusion with alarm_cancel and timer_callback.
1148d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chungvoid alarm_set(alarm_t *alarm, period_ms_t deadline, alarm_callback_t cb, void *data) {
115f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen  assert(alarms != NULL);
11668d739365bf650fe7fecf99cd3bfe63a0d41bd12Adam Cohen  assert(alarm != NULL);
117e0f66b546994a9bdee452851c17a148db02ec300Adam Cohen  assert(cb != NULL);
118f34bab59fc0260f926aec44d044883dce1b4191fAdam Cohen
11988127038178b3bbf0eb91103a31e682cc0615074Winson Chung  pthread_mutex_lock(&monitor);
12088127038178b3bbf0eb91103a31e682cc0615074Winson Chung
12188127038178b3bbf0eb91103a31e682cc0615074Winson Chung  // If the alarm is currently set and it's at the start of the list,
12288127038178b3bbf0eb91103a31e682cc0615074Winson Chung  // we'll need to re-schedule since we've adjusted the earliest deadline.
12388127038178b3bbf0eb91103a31e682cc0615074Winson Chung  bool needs_reschedule = (!list_is_empty(alarms) && list_front(alarms) == alarm);
1248f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn  if (alarm->callback)
125aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    list_remove(alarms, alarm);
1260142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka
12731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  alarm->deadline = now() + deadline;
12821f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen  alarm->callback = cb;
129d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka  alarm->data = data;
13021f12b52a54d2658ed14fcf7bb1ca17a198f62beAdam Cohen
13131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  // Add it into the timer list sorted by deadline (earliest deadline first).
13231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  if (list_is_empty(alarms))
13331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    list_prepend(alarms, alarm);
13431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  else
135aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    for (list_node_t *node = list_begin(alarms); node != list_end(alarms); node = list_next(node)) {
13670864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey      list_node_t *next = list_next(node);
13770864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey      if (next == list_end(alarms) || ((alarm_t *)list_node(next))->deadline >= alarm->deadline) {
13870864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        list_insert_after(alarms, node, alarm);
13970864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey        break;
14031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project      }
1416569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    }
1426569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy
1436569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy  // If the new alarm has the earliest deadline, we need to re-evaluate our schedule.
1446569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy  if (needs_reschedule || (!list_is_empty(alarms) && list_front(alarms) == alarm))
1456569f2c80e179c2f8ed73dae6b01d971ec20f005Patrick Dubroy    reschedule();
14631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1470589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato  pthread_mutex_unlock(&monitor);
14800acb123c5100f06b8e89e8ec8978ebafc6f6d26Joe Onorato}
149aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1504516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurkavoid alarm_cancel(alarm_t *alarm) {
1514516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka  assert(alarms != NULL);
15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  assert(alarm != NULL);
15370864289fba6daf07b8de98524cdfb765a62552dJeff Sharkey
1540280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka  pthread_mutex_lock(&monitor);
155a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka
1564516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka  bool needs_reschedule = (!list_is_empty(alarms) && list_front(alarms) == alarm);
1574516c11039d77066281f69f9b5d30fdaf1bc05aeMichael Jurka
158a63c452f5bd491ba9b28c332ccedc6c6c7e2f3ccMichael Jurka  list_remove(alarms, alarm);
1590280c3be4d9f8fc6fdf015b7ecd276eb26f76f2dMichael Jurka  alarm->deadline = 0;
16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  alarm->callback = NULL;
161c2f7f4794867cd1b3e97fd0f379ad8ad15958a6cMichael Jurka  alarm->data = NULL;
162d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka
163d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen  if (needs_reschedule)
164d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    reschedule();
16531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
1668a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy  pthread_mutex_unlock(&monitor);
1678a73c51ee87b6d9b12daba188034889caf7a905bRomain Guy
168aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung  // If the callback for |alarm| is in progress, wait here until it completes.
1691262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy  pthread_mutex_lock(&alarm->callback_lock);
170dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka  pthread_mutex_unlock(&alarm->callback_lock);
171c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka}
172c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka
173bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurkastatic bool lazy_initialize(void) {
174b8e14479da7209ca811a753b3256fe4a0b49a873Michael Jurka  assert(alarms == NULL);
175af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka
176af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka  pthread_mutex_init(&monitor, NULL);
177d3ef3065ab0941567c45e9aec98783138b623c68Michael Jurka
178883f55b1d261862b0de1b43af0b17d351761a9c6Michael Jurka  alarms = list_new(NULL);
179af91de06b99e2d5d41ce79fefa34ce2111e51917Michael Jurka  if (!alarms) {
1803c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka    ALOGE("%s unable to allocate alarm list.", __func__);
181dee0589388ba0f6373912e18bf86243282fb3b9bMichael Jurka    return false;
18254fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy  }
1831262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy
1841262e369484ce7f2565655ed80e6299232c70bd7Patrick Dubroy  return true;
18554fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy}
18654fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroy
18754fa3b95557c283976e8c1aa8a157b460b0b4513Patrick Dubroystatic period_ms_t now(void) {
1888e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy  assert(alarms != NULL);
1894be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato
1908e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy  struct timespec ts;
1918e58e916061cbe2623697efac0924f2aa3753a92Patrick Dubroy  if (clock_gettime(CLOCK_ID, &ts) == -1) {
1924be866d3a1665aa2098cb5d38d535b1ad1aab6d6Joe Onorato    ALOGE("%s unable to get current time: %s", __func__, strerror(errno));
193cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    return 0;
194cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy  }
195cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy
196cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy  return (ts.tv_sec * 1000LL) + (ts.tv_nsec / 1000000LL);
197cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy}
198a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
199a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung// Warning: this function is called in the context of an unknown thread.
200a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung// As a result, it must be thread-safe relative to other operations on
2016b879f0a5885274a85333531e091283405d490ccAdam Lesinski// the alarm list.
2026b879f0a5885274a85333531e091283405d490ccAdam Lesinskistatic void timer_callback(void *ptr) {
2036b879f0a5885274a85333531e091283405d490ccAdam Lesinski  alarm_t *alarm = (alarm_t *)ptr;
2046b879f0a5885274a85333531e091283405d490ccAdam Lesinski  assert(alarm != NULL);
2056b879f0a5885274a85333531e091283405d490ccAdam Lesinski
206c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka  pthread_mutex_lock(&monitor);
207c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
208c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka  bool alarm_valid = list_remove(alarms, alarm);
209c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka  alarm_callback_t callback = alarm->callback;
210c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka  void *data = alarm->data;
211c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
212c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka  alarm->deadline = 0;
213c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka  alarm->callback = NULL;
214c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka  alarm->data = NULL;
215c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka
216c5b262ccf639fedac2aff5bb8238342f95396338Michael Jurka  reschedule();
21731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  // The alarm was cancelled before we got to it. Release the monitor
21931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  // lock and exit right away since there's nothing left to do.
22031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  if (!alarm_valid) {
2210142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    pthread_mutex_unlock(&monitor);
22231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    return;
22331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  }
22431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
22531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  // Downgrade lock.
22631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  pthread_mutex_lock(&alarm->callback_lock);
22731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  pthread_mutex_unlock(&monitor);
22831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
22931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  callback(data);
23031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2310142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka  pthread_mutex_unlock(&alarm->callback_lock);
23231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
23331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project// NOTE: must be called with monitor lock.
23531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectstatic void reschedule(void) {
2360142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka  assert(alarms != NULL);
2375f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka
2385f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka  if (timer_set) {
2395f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    timer_delete(timer);
2405f1c509d5ad1954a7e38e77db4d5f27c7345fd39Michael Jurka    timer_set = false;
24131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  }
2428f573952b8729b4319043ae0908997ecd2d68951Dianne Hackborn
243aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung  if (list_is_empty(alarms)) {
244aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    bt_os_callouts->release_wake_lock(WAKE_LOCK_ID);
245aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    return;
246d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen  }
247d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen
2480142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka  alarm_t *next = list_front(alarms);
24931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  int64_t next_exp = next->deadline - now();
25031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project  if (next_exp < TIMER_INTERVAL_FOR_WAKELOCK_IN_MS) {
251d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen    int status = bt_os_callouts->acquire_wake_lock(WAKE_LOCK_ID);
2520d44e9482b95d8f163b28bf20131c4349185b589Joe Onorato    if (status != BT_STATUS_SUCCESS) {
2530142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka      ALOGE("%s unable to acquire wake lock: %d", __func__, status);
25431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project      return;
25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
25731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    struct sigevent sigevent;
25831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    memset(&sigevent, 0, sizeof(sigevent));
25931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    sigevent.sigev_notify = SIGEV_THREAD;
2600142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    sigevent.sigev_notify_function = (void (*)(union sigval))timer_callback;
2610589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    sigevent.sigev_value.sival_ptr = next;
2620142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka    if (timer_create(CLOCK_ID, &sigevent, &timer) == -1) {
2630142d49e1378a7155bcca1fb59965d9e73016dbcMichael Jurka      ALOGE("%s unable to create timer: %s", __func__, strerror(errno));
2640589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato      return;
2650589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    }
266a9abd0e0bdedb5cbbd12b84cb83037a735e79a20Winson Chung
267cd68ff5b88de9b5136ff5a9ef698e4db2fc5db66Patrick Dubroy    struct itimerspec wakeup_time;
26831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    memset(&wakeup_time, 0, sizeof(wakeup_time));
269b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung    wakeup_time.it_value.tv_sec = (next->deadline / 1000);
270b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung    wakeup_time.it_value.tv_nsec = (next->deadline % 1000) * 1000000LL;
271b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung    if (timer_settime(timer, TIMER_ABSTIME, &wakeup_time, NULL) == -1) {
2728d006d5e144ae33e509ea42e0b9760ef6c5bc884Winson Chung      ALOGE("%s unable to set timer: %s", __func__, strerror(errno));
273b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung      timer_delete(timer);
274b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung      return;
275b4b7fa7c0383b6af58d73d3e024b91d586148cf8Winson Chung    }
2769171e6d8a2b7b5aa136617b9779a8bbadc5259f7Winson Chung    timer_set = true;
2778edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka  } else {
2783c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka    if (!bt_os_callouts->set_wake_alarm(next_exp, true, timer_callback, next))
279c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka      ALOGE("%s unable to set wake alarm for %" PRId64 "ms.", __func__, next_exp);
280c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka
281bea15195346bab3c52b0156e92f2b71f0811b210Michael Jurka    bt_os_callouts->release_wake_lock(WAKE_LOCK_ID);
282c0e8fcae492730210b2b8b6d5bb3d65636bad245Michael Jurka  }
2833c4c20fbe682cb4b3ef94f09afe0af09171583f3Michael Jurka}
2848edd75c8bb0729a10cb39f614183e3e9ae4288e8Michael Jurka