diff options
author | Marie Janssen <jamuraa@google.com> | 2015-12-09 10:08:25 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-02-16 05:00:27 -0800 |
commit | b20358ca321f22ab073cf2107fef299017943de4 (patch) | |
tree | 69b29cf647f284235dedce7bb91e5129a984397d | |
parent | af69c1e623a79119e9b8180d23671a661bdb1eab (diff) | |
download | android_system_bt-b20358ca321f22ab073cf2107fef299017943de4.tar.gz android_system_bt-b20358ca321f22ab073cf2107fef299017943de4.tar.bz2 android_system_bt-b20358ca321f22ab073cf2107fef299017943de4.zip |
Fix crashes with lots of discovered LE devices
When loads of devices are discovered a config file which is too large
can be written out, which causes the BT daemon to crash on startup.
This limits the number of config entries for unpaired devices which
are initialized, and prevents a large number from being saved to the
filesystem.
CRs-Fixed: 953993
Bug: 26071376
Change-Id: I4a74094f57a82b17f94e99a819974b8bc8082184
(cherry picked from commit d77f1999ecece56c1cbb333f4ddc26f0b5bac2c5)
-rw-r--r-- | btif/src/btif_config.c | 85 |
1 files changed, 42 insertions, 43 deletions
diff --git a/btif/src/btif_config.c b/btif/src/btif_config.c index c94e449f8..aad4fa6b9 100644 --- a/btif/src/btif_config.c +++ b/btif/src/btif_config.c @@ -43,8 +43,9 @@ static const char *CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_config.conf"; static const char *LEGACY_CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_config.xml"; static const period_ms_t CONFIG_SETTLE_PERIOD_MS = 3000; -static void timer_config_saving(void* data); -static void timer_config_save(UINT16 event, char* p_param); +static void timer_config_save_cb(void *data); +static void btif_config_write(void); +static void btif_config_devcache_cleanup(void); // TODO(zachoverflow): Move these two functions out, because they are too specific for this file // {grumpy-cat/no, monty-python/you-make-me-sad} @@ -109,6 +110,8 @@ static future_t *init(void) { unlink(LEGACY_CONFIG_FILE_PATH); } + btif_config_devcache_cleanup(); + // TODO(sharvil): use a non-wake alarm for this once we have // API support for it. There's no need to wake the system to // write back to disk. @@ -348,7 +351,7 @@ void btif_config_save(void) { assert(alarm_timer != NULL); assert(config != NULL); - alarm_set(alarm_timer, CONFIG_SETTLE_PERIOD_MS, timer_config_saving, NULL); + alarm_set(alarm_timer, CONFIG_SETTLE_PERIOD_MS, timer_config_save_cb, NULL); } void btif_config_flush(void) { @@ -357,10 +360,7 @@ void btif_config_flush(void) { alarm_cancel(alarm_timer); - pthread_mutex_lock(&lock); - config_save(config, CONFIG_FILE_PATH); - config_flush(CONFIG_FILE_PATH); - pthread_mutex_unlock(&lock); + btif_config_write(); } int btif_config_clear(void){ @@ -383,52 +383,51 @@ int btif_config_clear(void){ return ret; } -static void timer_config_saving(UNUSED_ATTR void* data) { - // calling file IO onto btif context instead of timer callback because - // it usually takes lots of time to be completed timer callback has big - // delayed during a2dp playback causing blip or choppiness. - btif_transfer_context(timer_config_save, 0, NULL, 0, NULL); +static void timer_config_save_cb(UNUSED_ATTR void *data) { + btif_config_write(); } -static void timer_config_save(UNUSED_ATTR UINT16 event, UNUSED_ATTR char* p_param) { +static void btif_config_write(void) { assert(config != NULL); assert(alarm_timer != NULL); - // Garbage collection process: the config file accumulates - // cached information about remote devices during regular - // inquiry scans. We remove some of these junk entries - // so the file doesn't grow indefinitely. We have to take care - // to make sure we don't remove information about bonded - // devices (hence the check for link keys). - static const size_t CACHE_MAX = 256; - const char *keys[CACHE_MAX]; - size_t num_keys = 0; - size_t total_candidates = 0; + btif_config_devcache_cleanup(); pthread_mutex_lock(&lock); - for (const config_section_node_t *snode = config_section_begin(config); snode != config_section_end(config); snode = config_section_next(snode)) { - const char *section = config_section_name(snode); - if (!string_is_bdaddr(section)) - continue; + config_save(config, CONFIG_FILE_PATH); + pthread_mutex_unlock(&lock); +} - if (config_has_key(config, section, "LinkKey") || - config_has_key(config, section, "LE_KEY_PENC") || - config_has_key(config, section, "LE_KEY_PID") || - config_has_key(config, section, "LE_KEY_PCSRK") || - config_has_key(config, section, "LE_KEY_LENC") || - config_has_key(config, section, "LE_KEY_LCSRK")) - continue; +static void btif_config_devcache_cleanup(void) { + assert(config != NULL); - if (num_keys < CACHE_MAX) - keys[num_keys++] = section; + // The config accumulates cached information about remote + // devices during regular inquiry scans. We remove some of these + // so the cache doesn't grow indefinitely. + // We don't remove information about bonded devices (which have link keys). + static const size_t ADDRS_MAX = 512; + size_t total_addrs = 0; - ++total_candidates; + pthread_mutex_lock(&lock); + const config_section_node_t *snode = config_section_begin(config); + while (snode != config_section_end(config)) { + const char *section = config_section_name(snode); + if (string_is_bdaddr(section)) { + ++total_addrs; + + if ((total_addrs > ADDRS_MAX) && + !config_has_key(config, section, "LinkKey") && + !config_has_key(config, section, "LE_KEY_PENC") && + !config_has_key(config, section, "LE_KEY_PID") && + !config_has_key(config, section, "LE_KEY_PCSRK") && + !config_has_key(config, section, "LE_KEY_LENC") && + !config_has_key(config, section, "LE_KEY_LCSRK")) { + snode = config_section_next(snode); + config_remove_section(config, section); + continue; + } + } + snode = config_section_next(snode); } - - if (total_candidates > CACHE_MAX * 2) - while (num_keys > 0) - config_remove_section(config, keys[--num_keys]); - - config_save(config, CONFIG_FILE_PATH); pthread_mutex_unlock(&lock); } |