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