btif_config.cc revision 6bd442f543972b072ef2cbbcf2f7c91202de1045
1/******************************************************************************
2 *
3 *  Copyright (C) 2014 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_btif_config"
20
21#include "btif_config.h"
22
23#include <assert.h>
24#include <ctype.h>
25#include <stdio.h>
26#include <string.h>
27#include <time.h>
28#include <unistd.h>
29#include <string>
30
31#include <mutex>
32
33#include "bt_types.h"
34#include "btcore/include/bdaddr.h"
35#include "btcore/include/module.h"
36#include "btif_api.h"
37#include "btif_common.h"
38#include "btif_config.h"
39#include "btif_config_transcode.h"
40#include "btif_util.h"
41#include "osi/include/alarm.h"
42#include "osi/include/allocator.h"
43#include "osi/include/compat.h"
44#include "osi/include/config.h"
45#include "osi/include/log.h"
46#include "osi/include/osi.h"
47#include "osi/include/properties.h"
48
49#define BT_CONFIG_SOURCE_TAG_NUM 1010001
50
51#define INFO_SECTION "Info"
52#define FILE_TIMESTAMP "TimeCreated"
53#define FILE_SOURCE "FileSource"
54#define TIME_STRING_LENGTH sizeof("YYYY-MM-DD HH:MM:SS")
55static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S";
56
57// TODO(armansito): Find a better way than searching by a hardcoded path.
58#if defined(OS_GENERIC)
59static const char* CONFIG_FILE_PATH = "bt_config.conf";
60static const char* CONFIG_BACKUP_PATH = "bt_config.bak";
61static const char* CONFIG_LEGACY_FILE_PATH = "bt_config.xml";
62#else   // !defined(OS_GENERIC)
63static const char* CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_config.conf";
64static const char* CONFIG_BACKUP_PATH = "/data/misc/bluedroid/bt_config.bak";
65static const char* CONFIG_LEGACY_FILE_PATH =
66    "/data/misc/bluedroid/bt_config.xml";
67#endif  // defined(OS_GENERIC)
68static const period_ms_t CONFIG_SETTLE_PERIOD_MS = 3000;
69
70static void timer_config_save_cb(void* data);
71static void btif_config_write(uint16_t event, char* p_param);
72static bool is_factory_reset(void);
73static void delete_config_files(void);
74static void btif_config_remove_unpaired(config_t* config);
75static void btif_config_remove_restricted(config_t* config);
76static config_t* btif_config_open(const char* filename);
77
78static enum ConfigSource {
79  NOT_LOADED,
80  ORIGINAL,
81  BACKUP,
82  LEGACY,
83  NEW_FILE,
84  RESET
85} btif_config_source = NOT_LOADED;
86
87static int btif_config_devices_loaded = -1;
88static char btif_config_time_created[TIME_STRING_LENGTH];
89
90// TODO(zachoverflow): Move these two functions out, because they are too
91// specific for this file
92// {grumpy-cat/no, monty-python/you-make-me-sad}
93bool btif_get_device_type(const BD_ADDR bd_addr, int* p_device_type) {
94  if (p_device_type == NULL) return false;
95
96  bt_bdaddr_t bda;
97  bdcpy(bda.address, bd_addr);
98
99  bdstr_t bd_addr_str;
100  bdaddr_to_string(&bda, bd_addr_str, sizeof(bd_addr_str));
101
102  if (!btif_config_get_int(bd_addr_str, "DevType", p_device_type)) return false;
103
104  LOG_DEBUG(LOG_TAG, "%s: Device [%s] type %d", __func__, bd_addr_str,
105            *p_device_type);
106  return true;
107}
108
109bool btif_get_address_type(const BD_ADDR bd_addr, int* p_addr_type) {
110  if (p_addr_type == NULL) return false;
111
112  bt_bdaddr_t bda;
113  bdcpy(bda.address, bd_addr);
114
115  bdstr_t bd_addr_str;
116  bdaddr_to_string(&bda, bd_addr_str, sizeof(bd_addr_str));
117
118  if (!btif_config_get_int(bd_addr_str, "AddrType", p_addr_type)) return false;
119
120  LOG_DEBUG(LOG_TAG, "%s: Device [%s] address type %d", __func__, bd_addr_str,
121            *p_addr_type);
122  return true;
123}
124
125static std::mutex config_lock;  // protects operations on |config|.
126static config_t* config;
127static alarm_t* config_timer;
128
129// Module lifecycle functions
130
131static future_t* init(void) {
132  std::unique_lock<std::mutex> lock(config_lock);
133
134  if (is_factory_reset()) delete_config_files();
135
136  std::string file_source;
137
138  config = btif_config_open(CONFIG_FILE_PATH);
139  btif_config_source = ORIGINAL;
140  if (!config) {
141    LOG_WARN(LOG_TAG, "%s unable to load config file: %s; using backup.",
142             __func__, CONFIG_FILE_PATH);
143    config = btif_config_open(CONFIG_BACKUP_PATH);
144    btif_config_source = BACKUP;
145    file_source = "Backup";
146  }
147  if (!config) {
148    LOG_WARN(LOG_TAG,
149             "%s unable to load backup; attempting to transcode legacy file.",
150             __func__);
151    config = btif_config_transcode(CONFIG_LEGACY_FILE_PATH);
152    btif_config_source = LEGACY;
153    file_source = "Legacy";
154  }
155  if (!config) {
156    LOG_ERROR(LOG_TAG,
157              "%s unable to transcode legacy file; creating empty config.",
158              __func__);
159    config = config_new_empty();
160    btif_config_source = NEW_FILE;
161    file_source = "Empty";
162  }
163
164  if (!file_source.empty())
165    config_set_string(config, INFO_SECTION, FILE_SOURCE, file_source.c_str());
166
167  if (!config) {
168    LOG_ERROR(LOG_TAG, "%s unable to allocate a config object.", __func__);
169    goto error;
170  }
171
172  btif_config_remove_unpaired(config);
173
174  // Cleanup temporary pairings if we have left guest mode
175  if (!is_restricted_mode()) btif_config_remove_restricted(config);
176
177  // Read or set config file creation timestamp
178  const char* time_str;
179  time_str = config_get_string(config, INFO_SECTION, FILE_TIMESTAMP, NULL);
180  if (time_str != NULL) {
181    strlcpy(btif_config_time_created, time_str, TIME_STRING_LENGTH);
182  } else {
183    time_t current_time = time(NULL);
184    struct tm* time_created = localtime(&current_time);
185    strftime(btif_config_time_created, TIME_STRING_LENGTH, TIME_STRING_FORMAT,
186             time_created);
187    config_set_string(config, INFO_SECTION, FILE_TIMESTAMP,
188                      btif_config_time_created);
189  }
190
191  // TODO(sharvil): use a non-wake alarm for this once we have
192  // API support for it. There's no need to wake the system to
193  // write back to disk.
194  config_timer = alarm_new("btif.config");
195  if (!config_timer) {
196    LOG_ERROR(LOG_TAG, "%s unable to create alarm.", __func__);
197    goto error;
198  }
199
200  LOG_EVENT_INT(BT_CONFIG_SOURCE_TAG_NUM, btif_config_source);
201
202  return future_new_immediate(FUTURE_SUCCESS);
203
204error:
205  alarm_free(config_timer);
206  config_free(config);
207  config_timer = NULL;
208  config = NULL;
209  btif_config_source = NOT_LOADED;
210  return future_new_immediate(FUTURE_FAIL);
211}
212
213static config_t* btif_config_open(const char* filename) {
214  config_t* config = config_new(filename);
215  if (!config) return NULL;
216
217  if (!config_has_section(config, "Adapter")) {
218    LOG_ERROR(LOG_TAG, "Config is missing adapter section");
219    config_free(config);
220    return NULL;
221  }
222
223  return config;
224}
225
226static future_t* shut_down(void) {
227  btif_config_flush();
228  return future_new_immediate(FUTURE_SUCCESS);
229}
230
231static future_t* clean_up(void) {
232  btif_config_flush();
233
234  alarm_free(config_timer);
235  config_free(config);
236  config_timer = NULL;
237  config = NULL;
238  return future_new_immediate(FUTURE_SUCCESS);
239}
240
241EXPORT_SYMBOL module_t btif_config_module = {.name = BTIF_CONFIG_MODULE,
242                                             .init = init,
243                                             .start_up = NULL,
244                                             .shut_down = shut_down,
245                                             .clean_up = clean_up};
246
247bool btif_config_has_section(const char* section) {
248  assert(config != NULL);
249  assert(section != NULL);
250
251  std::unique_lock<std::mutex> lock(config_lock);
252  return config_has_section(config, section);
253}
254
255bool btif_config_exist(const char* section, const char* key) {
256  assert(config != NULL);
257  assert(section != NULL);
258  assert(key != NULL);
259
260  std::unique_lock<std::mutex> lock(config_lock);
261  return config_has_key(config, section, key);
262}
263
264bool btif_config_get_int(const char* section, const char* key, int* value) {
265  assert(config != NULL);
266  assert(section != NULL);
267  assert(key != NULL);
268  assert(value != NULL);
269
270  std::unique_lock<std::mutex> lock(config_lock);
271  bool ret = config_has_key(config, section, key);
272  if (ret) *value = config_get_int(config, section, key, *value);
273
274  return ret;
275}
276
277bool btif_config_set_int(const char* section, const char* key, int value) {
278  assert(config != NULL);
279  assert(section != NULL);
280  assert(key != NULL);
281
282  std::unique_lock<std::mutex> lock(config_lock);
283  config_set_int(config, section, key, value);
284
285  return true;
286}
287
288bool btif_config_get_str(const char* section, const char* key, char* value,
289                         int* size_bytes) {
290  assert(config != NULL);
291  assert(section != NULL);
292  assert(key != NULL);
293  assert(value != NULL);
294  assert(size_bytes != NULL);
295
296  {
297    std::unique_lock<std::mutex> lock(config_lock);
298    const char* stored_value = config_get_string(config, section, key, NULL);
299    if (!stored_value) return false;
300    strlcpy(value, stored_value, *size_bytes);
301  }
302
303  *size_bytes = strlen(value) + 1;
304  return true;
305}
306
307bool btif_config_set_str(const char* section, const char* key,
308                         const char* value) {
309  assert(config != NULL);
310  assert(section != NULL);
311  assert(key != NULL);
312  assert(value != NULL);
313
314  std::unique_lock<std::mutex> lock(config_lock);
315  config_set_string(config, section, key, value);
316  return true;
317}
318
319bool btif_config_get_bin(const char* section, const char* key, uint8_t* value,
320                         size_t* length) {
321  assert(config != NULL);
322  assert(section != NULL);
323  assert(key != NULL);
324  assert(value != NULL);
325  assert(length != NULL);
326
327  std::unique_lock<std::mutex> lock(config_lock);
328  const char* value_str = config_get_string(config, section, key, NULL);
329
330  if (!value_str) return false;
331
332  size_t value_len = strlen(value_str);
333  if ((value_len % 2) != 0 || *length < (value_len / 2)) return false;
334
335  for (size_t i = 0; i < value_len; ++i)
336    if (!isxdigit(value_str[i])) return false;
337
338  for (*length = 0; *value_str; value_str += 2, *length += 1)
339    sscanf(value_str, "%02hhx", &value[*length]);
340
341  return true;
342}
343
344size_t btif_config_get_bin_length(const char* section, const char* key) {
345  assert(config != NULL);
346  assert(section != NULL);
347  assert(key != NULL);
348
349  std::unique_lock<std::mutex> lock(config_lock);
350  const char* value_str = config_get_string(config, section, key, NULL);
351  if (!value_str) return 0;
352
353  size_t value_len = strlen(value_str);
354  return ((value_len % 2) != 0) ? 0 : (value_len / 2);
355}
356
357bool btif_config_set_bin(const char* section, const char* key,
358                         const uint8_t* value, size_t length) {
359  const char* lookup = "0123456789abcdef";
360
361  assert(config != NULL);
362  assert(section != NULL);
363  assert(key != NULL);
364
365  if (length > 0) assert(value != NULL);
366
367  char* str = (char*)osi_calloc(length * 2 + 1);
368
369  for (size_t i = 0; i < length; ++i) {
370    str[(i * 2) + 0] = lookup[(value[i] >> 4) & 0x0F];
371    str[(i * 2) + 1] = lookup[value[i] & 0x0F];
372  }
373
374  {
375    std::unique_lock<std::mutex> lock(config_lock);
376    config_set_string(config, section, key, str);
377  }
378
379  osi_free(str);
380  return true;
381}
382
383const btif_config_section_iter_t* btif_config_section_begin(void) {
384  assert(config != NULL);
385  return (const btif_config_section_iter_t*)config_section_begin(config);
386}
387
388const btif_config_section_iter_t* btif_config_section_end(void) {
389  assert(config != NULL);
390  return (const btif_config_section_iter_t*)config_section_end(config);
391}
392
393const btif_config_section_iter_t* btif_config_section_next(
394    const btif_config_section_iter_t* section) {
395  assert(config != NULL);
396  assert(section != NULL);
397  return (const btif_config_section_iter_t*)config_section_next(
398      (const config_section_node_t*)section);
399}
400
401const char* btif_config_section_name(
402    const btif_config_section_iter_t* section) {
403  assert(config != NULL);
404  assert(section != NULL);
405  return config_section_name((const config_section_node_t*)section);
406}
407
408bool btif_config_remove(const char* section, const char* key) {
409  assert(config != NULL);
410  assert(section != NULL);
411  assert(key != NULL);
412
413  std::unique_lock<std::mutex> lock(config_lock);
414  return config_remove_key(config, section, key);
415}
416
417void btif_config_save(void) {
418  assert(config != NULL);
419  assert(config_timer != NULL);
420
421  alarm_set(config_timer, CONFIG_SETTLE_PERIOD_MS, timer_config_save_cb, NULL);
422}
423
424void btif_config_flush(void) {
425  assert(config != NULL);
426  assert(config_timer != NULL);
427
428  alarm_cancel(config_timer);
429  btif_config_write(0, NULL);
430}
431
432bool btif_config_clear(void) {
433  assert(config != NULL);
434  assert(config_timer != NULL);
435
436  alarm_cancel(config_timer);
437
438  std::unique_lock<std::mutex> lock(config_lock);
439  config_free(config);
440
441  config = config_new_empty();
442  if (config == NULL) return false;
443
444  bool ret = config_save(config, CONFIG_FILE_PATH);
445  btif_config_source = RESET;
446  return ret;
447}
448
449static void timer_config_save_cb(UNUSED_ATTR void* data) {
450  // Moving file I/O to btif context instead of timer callback because
451  // it usually takes a lot of time to be completed, introducing
452  // delays during A2DP playback causing blips or choppiness.
453  btif_transfer_context(btif_config_write, 0, NULL, 0, NULL);
454}
455
456static void btif_config_write(UNUSED_ATTR uint16_t event,
457                              UNUSED_ATTR char* p_param) {
458  assert(config != NULL);
459  assert(config_timer != NULL);
460
461  std::unique_lock<std::mutex> lock(config_lock);
462  rename(CONFIG_FILE_PATH, CONFIG_BACKUP_PATH);
463  config_t* config_paired = config_new_clone(config);
464  btif_config_remove_unpaired(config_paired);
465  config_save(config_paired, CONFIG_FILE_PATH);
466  config_free(config_paired);
467}
468
469static void btif_config_remove_unpaired(config_t* conf) {
470  assert(conf != NULL);
471  int paired_devices = 0;
472
473  // The paired config used to carry information about
474  // discovered devices during regular inquiry scans.
475  // We remove these now and cache them in memory instead.
476  const config_section_node_t* snode = config_section_begin(conf);
477  while (snode != config_section_end(conf)) {
478    const char* section = config_section_name(snode);
479    if (string_is_bdaddr(section)) {
480      if (!config_has_key(conf, section, "LinkKey") &&
481          !config_has_key(conf, section, "LE_KEY_PENC") &&
482          !config_has_key(conf, section, "LE_KEY_PID") &&
483          !config_has_key(conf, section, "LE_KEY_PCSRK") &&
484          !config_has_key(conf, section, "LE_KEY_LENC") &&
485          !config_has_key(conf, section, "LE_KEY_LCSRK")) {
486        snode = config_section_next(snode);
487        config_remove_section(conf, section);
488        continue;
489      }
490      paired_devices++;
491    }
492    snode = config_section_next(snode);
493  }
494
495  // should only happen once, at initial load time
496  if (btif_config_devices_loaded == -1)
497    btif_config_devices_loaded = paired_devices;
498}
499
500void btif_debug_config_dump(int fd) {
501  dprintf(fd, "\nBluetooth Config:\n");
502
503  dprintf(fd, "  Config Source: ");
504  switch (btif_config_source) {
505    case NOT_LOADED:
506      dprintf(fd, "Not loaded\n");
507      break;
508    case ORIGINAL:
509      dprintf(fd, "Original file\n");
510      break;
511    case BACKUP:
512      dprintf(fd, "Backup file\n");
513      break;
514    case LEGACY:
515      dprintf(fd, "Legacy file\n");
516      break;
517    case NEW_FILE:
518      dprintf(fd, "New file\n");
519      break;
520    case RESET:
521      dprintf(fd, "Reset file\n");
522      break;
523  }
524
525  dprintf(fd, "  Devices loaded: %d\n", btif_config_devices_loaded);
526  dprintf(fd, "  File created/tagged: %s\n", btif_config_time_created);
527  dprintf(fd, "  File source: %s\n",
528          config_get_string(config, INFO_SECTION, FILE_SOURCE, "Original"));
529}
530
531static void btif_config_remove_restricted(config_t* config) {
532  assert(config != NULL);
533
534  const config_section_node_t* snode = config_section_begin(config);
535  while (snode != config_section_end(config)) {
536    const char* section = config_section_name(snode);
537    if (string_is_bdaddr(section) &&
538        config_has_key(config, section, "Restricted")) {
539      BTIF_TRACE_DEBUG("%s: Removing restricted device %s", __func__, section);
540      config_remove_section(config, section);
541    }
542    snode = config_section_next(snode);
543  }
544}
545
546static bool is_factory_reset(void) {
547  char factory_reset[PROPERTY_VALUE_MAX] = {0};
548  osi_property_get("persist.bluetooth.factoryreset", factory_reset, "false");
549  return strncmp(factory_reset, "true", 4) == 0;
550}
551
552static void delete_config_files(void) {
553  remove(CONFIG_FILE_PATH);
554  remove(CONFIG_BACKUP_PATH);
555  osi_property_set("persist.bluetooth.factoryreset", "false");
556}
557