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(¤t_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