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