1 /******************************************************************************
2  *
3  *  Copyright 2015 Google, Inc.
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #define LOG_TAG "bt_osi_wakelock"
20 
21 #include "osi/include/wakelock.h"
22 
23 #include <bluetooth/log.h>
24 #include <fcntl.h>
25 #include <hardware/bluetooth.h>
26 #include <pthread.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <time.h>
31 #include <unistd.h>
32 
33 #include <mutex>
34 #include <string>
35 
36 #include "common/metrics.h"
37 #include "os/log.h"
38 #include "osi/include/osi.h"
39 
40 using bluetooth::common::BluetoothMetricsLogger;
41 using namespace bluetooth;
42 
43 static bt_os_callouts_t* wakelock_os_callouts = NULL;
44 static bool is_native = true;
45 
46 static const clockid_t CLOCK_ID = CLOCK_BOOTTIME;
47 static const char* WAKE_LOCK_ID = "bluetooth_timer";
48 static const std::string DEFAULT_WAKE_LOCK_PATH = "/sys/power/wake_lock";
49 static const std::string DEFAULT_WAKE_UNLOCK_PATH = "/sys/power/wake_unlock";
50 static std::string wake_lock_path;
51 static std::string wake_unlock_path;
52 static ssize_t locked_id_len = -1;
53 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
54 static int wake_lock_fd = INVALID_FD;
55 static int wake_unlock_fd = INVALID_FD;
56 
57 // Wakelock statistics for the "bluetooth_timer"
58 typedef struct {
59   bool is_acquired;
60   size_t acquired_count;
61   size_t released_count;
62   size_t acquired_errors;
63   size_t released_errors;
64   uint64_t min_acquired_interval_ms;
65   uint64_t max_acquired_interval_ms;
66   uint64_t last_acquired_interval_ms;
67   uint64_t total_acquired_interval_ms;
68   uint64_t last_acquired_timestamp_ms;
69   uint64_t last_released_timestamp_ms;
70   uint64_t last_reset_timestamp_ms;
71   int last_acquired_error;
72   int last_released_error;
73 } wakelock_stats_t;
74 
75 static wakelock_stats_t wakelock_stats;
76 
77 // This mutex ensures that the functions that update and dump the statistics
78 // are executed serially.
79 static std::mutex stats_mutex;
80 
81 static bt_status_t wakelock_acquire_callout(void);
82 static bt_status_t wakelock_acquire_native(void);
83 static bt_status_t wakelock_release_callout(void);
84 static bt_status_t wakelock_release_native(void);
85 static void wakelock_initialize(void);
86 static void wakelock_initialize_native(void);
87 static void reset_wakelock_stats(void);
88 static void update_wakelock_acquired_stats(bt_status_t acquired_status);
89 static void update_wakelock_released_stats(bt_status_t released_status);
90 
wakelock_set_os_callouts(bt_os_callouts_t * callouts)91 void wakelock_set_os_callouts(bt_os_callouts_t* callouts) {
92   wakelock_os_callouts = callouts;
93   is_native = (wakelock_os_callouts == NULL);
94   log::info("set to {}", (is_native) ? "native" : "non-native");
95 }
96 
wakelock_acquire(void)97 bool wakelock_acquire(void) {
98   pthread_once(&initialized, wakelock_initialize);
99 
100   bt_status_t status = BT_STATUS_FAIL;
101 
102   if (is_native)
103     status = wakelock_acquire_native();
104   else
105     status = wakelock_acquire_callout();
106 
107   update_wakelock_acquired_stats(status);
108 
109   if (status != BT_STATUS_SUCCESS)
110     log::error("unable to acquire wake lock: {}", status);
111 
112   return (status == BT_STATUS_SUCCESS);
113 }
114 
wakelock_acquire_callout(void)115 static bt_status_t wakelock_acquire_callout(void) {
116   return static_cast<bt_status_t>(
117       wakelock_os_callouts->acquire_wake_lock(WAKE_LOCK_ID));
118 }
119 
wakelock_acquire_native(void)120 static bt_status_t wakelock_acquire_native(void) {
121   if (wake_lock_fd == INVALID_FD) {
122     log::error("lock not acquired, invalid fd");
123     return BT_STATUS_PARM_INVALID;
124   }
125 
126   if (wake_unlock_fd == INVALID_FD) {
127     log::error("not acquiring lock: can't release lock");
128     return BT_STATUS_PARM_INVALID;
129   }
130 
131   long lock_name_len = strlen(WAKE_LOCK_ID);
132   locked_id_len = write(wake_lock_fd, WAKE_LOCK_ID, lock_name_len);
133   if (locked_id_len == -1) {
134     log::error("wake lock not acquired: {}", strerror(errno));
135     return BT_STATUS_WAKELOCK_ERROR;
136   } else if (locked_id_len < lock_name_len) {
137     // TODO (jamuraa): this is weird. maybe we should release and retry.
138     log::warn("wake lock truncated to {} chars", locked_id_len);
139   }
140   return BT_STATUS_SUCCESS;
141 }
142 
wakelock_release(void)143 bool wakelock_release(void) {
144   pthread_once(&initialized, wakelock_initialize);
145 
146   bt_status_t status = BT_STATUS_FAIL;
147 
148   if (is_native)
149     status = wakelock_release_native();
150   else
151     status = wakelock_release_callout();
152 
153   update_wakelock_released_stats(status);
154 
155   return (status == BT_STATUS_SUCCESS);
156 }
157 
wakelock_release_callout(void)158 static bt_status_t wakelock_release_callout(void) {
159   return static_cast<bt_status_t>(
160       wakelock_os_callouts->release_wake_lock(WAKE_LOCK_ID));
161 }
162 
wakelock_release_native(void)163 static bt_status_t wakelock_release_native(void) {
164   if (wake_unlock_fd == INVALID_FD) {
165     log::error("lock not released, invalid fd");
166     return BT_STATUS_PARM_INVALID;
167   }
168 
169   ssize_t wrote_name_len = write(wake_unlock_fd, WAKE_LOCK_ID, locked_id_len);
170   if (wrote_name_len == -1) {
171     log::error("can't release wake lock: {}", strerror(errno));
172   } else if (wrote_name_len < locked_id_len) {
173     log::error("lock release only wrote {}, assuming released", wrote_name_len);
174   }
175   return BT_STATUS_SUCCESS;
176 }
177 
wakelock_initialize(void)178 static void wakelock_initialize(void) {
179   reset_wakelock_stats();
180 
181   if (is_native) wakelock_initialize_native();
182 }
183 
wakelock_initialize_native(void)184 static void wakelock_initialize_native(void) {
185   log::info("opening wake locks");
186 
187   if (wake_lock_path.empty()) wake_lock_path = DEFAULT_WAKE_LOCK_PATH;
188 
189   wake_lock_fd = open(wake_lock_path.c_str(), O_RDWR | O_CLOEXEC);
190   if (wake_lock_fd == INVALID_FD) {
191     log::error("can't open wake lock {}: {}", wake_lock_path, strerror(errno));
192   }
193 
194   if (wake_unlock_path.empty()) wake_unlock_path = DEFAULT_WAKE_UNLOCK_PATH;
195 
196   wake_unlock_fd = open(wake_unlock_path.c_str(), O_RDWR | O_CLOEXEC);
197   if (wake_unlock_fd == INVALID_FD) {
198     log::error("can't open wake unlock {}: {}", wake_unlock_path,
199                strerror(errno));
200   }
201 }
202 
wakelock_cleanup(void)203 void wakelock_cleanup(void) {
204   if (wakelock_stats.is_acquired) {
205     log::error("releasing wake lock as part of cleanup");
206     wakelock_release();
207   }
208   wake_lock_path.clear();
209   wake_unlock_path.clear();
210   initialized = PTHREAD_ONCE_INIT;
211 }
212 
wakelock_set_paths(const char * lock_path,const char * unlock_path)213 void wakelock_set_paths(const char* lock_path, const char* unlock_path) {
214   if (lock_path) wake_lock_path = lock_path;
215 
216   if (unlock_path) wake_unlock_path = unlock_path;
217 }
218 
now_ms(void)219 static uint64_t now_ms(void) {
220   struct timespec ts;
221   if (clock_gettime(CLOCK_ID, &ts) == -1) {
222     log::error("unable to get current time: {}", strerror(errno));
223     return 0;
224   }
225 
226   return (ts.tv_sec * 1000LL) + (ts.tv_nsec / 1000000LL);
227 }
228 
229 // Reset the Bluetooth wakelock statistics.
230 // This function is thread-safe.
reset_wakelock_stats(void)231 static void reset_wakelock_stats(void) {
232   std::lock_guard<std::mutex> lock(stats_mutex);
233 
234   wakelock_stats.is_acquired = false;
235   wakelock_stats.acquired_count = 0;
236   wakelock_stats.released_count = 0;
237   wakelock_stats.acquired_errors = 0;
238   wakelock_stats.released_errors = 0;
239   wakelock_stats.min_acquired_interval_ms = 0;
240   wakelock_stats.max_acquired_interval_ms = 0;
241   wakelock_stats.last_acquired_interval_ms = 0;
242   wakelock_stats.total_acquired_interval_ms = 0;
243   wakelock_stats.last_acquired_timestamp_ms = 0;
244   wakelock_stats.last_released_timestamp_ms = 0;
245   wakelock_stats.last_reset_timestamp_ms = now_ms();
246 }
247 
248 //
249 // Update the Bluetooth acquire wakelock statistics.
250 //
251 // This function should be called every time when the wakelock is acquired.
252 // |acquired_status| is the status code that was return when the wakelock was
253 // acquired.
254 // This function is thread-safe.
255 //
update_wakelock_acquired_stats(bt_status_t acquired_status)256 static void update_wakelock_acquired_stats(bt_status_t acquired_status) {
257   const uint64_t just_now_ms = now_ms();
258 
259   std::lock_guard<std::mutex> lock(stats_mutex);
260 
261   if (acquired_status != BT_STATUS_SUCCESS) {
262     wakelock_stats.acquired_errors++;
263     wakelock_stats.last_acquired_error = acquired_status;
264   }
265 
266   if (wakelock_stats.is_acquired) {
267     return;
268   }
269 
270   wakelock_stats.is_acquired = true;
271   wakelock_stats.acquired_count++;
272   wakelock_stats.last_acquired_timestamp_ms = just_now_ms;
273 
274   BluetoothMetricsLogger::GetInstance()->LogWakeEvent(
275       bluetooth::common::WAKE_EVENT_ACQUIRED, "", "", just_now_ms);
276 }
277 
278 //
279 // Update the Bluetooth release wakelock statistics.
280 //
281 // This function should be called every time when the wakelock is released.
282 // |released_status| is the status code that was return when the wakelock was
283 // released.
284 // This function is thread-safe.
285 //
update_wakelock_released_stats(bt_status_t released_status)286 static void update_wakelock_released_stats(bt_status_t released_status) {
287   const uint64_t just_now_ms = now_ms();
288 
289   std::lock_guard<std::mutex> lock(stats_mutex);
290 
291   if (released_status != BT_STATUS_SUCCESS) {
292     wakelock_stats.released_errors++;
293     wakelock_stats.last_released_error = released_status;
294   }
295 
296   if (!wakelock_stats.is_acquired) {
297     return;
298   }
299 
300   wakelock_stats.is_acquired = false;
301   wakelock_stats.released_count++;
302   wakelock_stats.last_released_timestamp_ms = just_now_ms;
303 
304   // Compute the acquired interval and update the statistics
305   uint64_t delta_ms = just_now_ms - wakelock_stats.last_acquired_timestamp_ms;
306   if (delta_ms < wakelock_stats.min_acquired_interval_ms ||
307       wakelock_stats.released_count == 1) {
308     wakelock_stats.min_acquired_interval_ms = delta_ms;
309   }
310   if (delta_ms > wakelock_stats.max_acquired_interval_ms) {
311     wakelock_stats.max_acquired_interval_ms = delta_ms;
312   }
313   wakelock_stats.last_acquired_interval_ms = delta_ms;
314   wakelock_stats.total_acquired_interval_ms += delta_ms;
315 
316   BluetoothMetricsLogger::GetInstance()->LogWakeEvent(
317       bluetooth::common::WAKE_EVENT_RELEASED, "", "", just_now_ms);
318 }
319 
wakelock_debug_dump(int fd)320 void wakelock_debug_dump(int fd) {
321   const uint64_t just_now_ms = now_ms();
322 
323   std::lock_guard<std::mutex> lock(stats_mutex);
324 
325   // Compute the last acquired interval if the wakelock is still acquired
326   uint64_t delta_ms = 0;
327   uint64_t last_interval_ms = wakelock_stats.last_acquired_interval_ms;
328   uint64_t min_interval_ms = wakelock_stats.min_acquired_interval_ms;
329   uint64_t max_interval_ms = wakelock_stats.max_acquired_interval_ms;
330   uint64_t avg_interval_ms = 0;
331 
332   if (wakelock_stats.is_acquired) {
333     delta_ms = just_now_ms - wakelock_stats.last_acquired_timestamp_ms;
334     if (delta_ms > max_interval_ms) max_interval_ms = delta_ms;
335     if (delta_ms < min_interval_ms) min_interval_ms = delta_ms;
336     last_interval_ms = delta_ms;
337   }
338   uint64_t total_interval_ms =
339       wakelock_stats.total_acquired_interval_ms + delta_ms;
340 
341   if (wakelock_stats.acquired_count > 0)
342     avg_interval_ms = total_interval_ms / wakelock_stats.acquired_count;
343 
344   dprintf(fd, "\nBluetooth Wakelock Statistics:\n");
345   dprintf(fd, "  Is acquired                    : %s\n",
346           wakelock_stats.is_acquired ? "true" : "false");
347   dprintf(fd, "  Acquired/released count        : %zu / %zu\n",
348           wakelock_stats.acquired_count, wakelock_stats.released_count);
349   dprintf(fd, "  Acquired/released error count  : %zu / %zu\n",
350           wakelock_stats.acquired_errors, wakelock_stats.released_errors);
351   dprintf(fd, "  Last acquire/release error code: %d / %d\n",
352           wakelock_stats.last_acquired_error,
353           wakelock_stats.last_released_error);
354   dprintf(fd, "  Last acquired time (ms)        : %llu\n",
355           (unsigned long long)last_interval_ms);
356   dprintf(fd, "  Acquired time min/max/avg (ms) : %llu / %llu / %llu\n",
357           (unsigned long long)min_interval_ms,
358           (unsigned long long)max_interval_ms,
359           (unsigned long long)avg_interval_ms);
360   dprintf(fd, "  Total acquired time (ms)       : %llu\n",
361           (unsigned long long)total_interval_ms);
362   dprintf(fd, "  Total run time (ms)            : %llu\n",
363           (unsigned long long)(just_now_ms -
364                                wakelock_stats.last_reset_timestamp_ms));
365 }
366