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