#include "bt_types.h"
#include "btcore/include/bdaddr.h"
#include "btcore/include/module.h"
-#include "btif_config_transcode.h"
+#include "btif_common.h"
+#include "btif_config.h"
#include "btif_util.h"
#include "osi/include/alarm.h"
#include "osi/include/allocator.h"
// TODO(armansito): Find a better way than searching by a hardcoded path.
#if defined(OS_GENERIC)
static const char *CONFIG_FILE_PATH = "bt_config.conf";
+static const char *CONFIG_BACKUP_PATH = "bt_config.bak";
#else // !defined(OS_GENERIC)
static const char *CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_config.conf";
+static const char *CONFIG_BACKUP_PATH = "/data/misc/bluedroid/bt_config.bak";
#endif // defined(OS_GENERIC)
-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_save_cb(void *data);
-static void btif_config_write(void);
+static void btif_config_write(UINT16 event, char *p_param);
static void btif_config_devcache_cleanup(void);
+static enum ConfigSource {
+ NOT_LOADED,
+ ORIGINAL,
+ BACKUP,
+ NEW_FILE,
+ RESET
+} btif_config_source = NOT_LOADED;
+
+
// TODO(zachoverflow): Move these two functions out, because they are too specific for this file
// {grumpy-cat/no, monty-python/you-make-me-sad}
bool btif_get_device_type(const BD_ADDR bd_addr, int *p_device_type)
static pthread_mutex_t lock; // protects operations on |config|.
static config_t *config;
-static alarm_t *alarm_timer;
+static alarm_t *config_timer;
// Module lifecycle functions
static future_t *init(void) {
pthread_mutex_init(&lock, NULL);
config = config_new(CONFIG_FILE_PATH);
+ btif_config_source = ORIGINAL;
if (!config) {
- LOG_WARN(LOG_TAG, "%s unable to load config file; attempting to transcode legacy file.", __func__);
- config = btif_config_transcode(LEGACY_CONFIG_FILE_PATH);
+ LOG_WARN(LOG_TAG, "%s unable to load config file: %s; using backup.",
+ __func__, CONFIG_FILE_PATH);
+ config = config_new(CONFIG_BACKUP_PATH);
+ btif_config_source = BACKUP;
if (!config) {
- LOG_WARN(LOG_TAG, "%s unable to transcode legacy file, starting unconfigured.", __func__);
+ LOG_ERROR(LOG_TAG, "%s unable to load backup; creating empty config.", __func__);
config = config_new_empty();
+ btif_config_source = NEW_FILE;
if (!config) {
LOG_ERROR(LOG_TAG, "%s unable to allocate a config object.", __func__);
goto error;
}
}
-
- if (config_save(config, CONFIG_FILE_PATH))
- 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.
- alarm_timer = alarm_new();
- if (!alarm_timer) {
+ config_timer = alarm_new("btif.config");
+ if (!config_timer) {
LOG_ERROR(LOG_TAG, "%s unable to create alarm.", __func__);
goto error;
}
return future_new_immediate(FUTURE_SUCCESS);
-error:;
- alarm_free(alarm_timer);
+error:
+ alarm_free(config_timer);
config_free(config);
pthread_mutex_destroy(&lock);
- alarm_timer = NULL;
+ config_timer = NULL;
config = NULL;
return future_new_immediate(FUTURE_FAIL);
}
static future_t *clean_up(void) {
btif_config_flush();
- alarm_free(alarm_timer);
+ alarm_free(config_timer);
config_free(config);
pthread_mutex_destroy(&lock);
- alarm_timer = NULL;
+ config_timer = NULL;
config = NULL;
return future_new_immediate(FUTURE_SUCCESS);
}
assert(value != NULL);
char *str = (char *)osi_calloc(length * 2 + 1);
- if (!str)
- return false;
for (size_t i = 0; i < length; ++i) {
str[(i * 2) + 0] = lookup[(value[i] >> 4) & 0x0F];
}
void btif_config_save(void) {
- assert(alarm_timer != NULL);
+ assert(config_timer != NULL);
assert(config != NULL);
- alarm_set(alarm_timer, CONFIG_SETTLE_PERIOD_MS, timer_config_save_cb, NULL);
+ alarm_set(config_timer, CONFIG_SETTLE_PERIOD_MS, timer_config_save_cb, NULL);
}
void btif_config_flush(void) {
assert(config != NULL);
- assert(alarm_timer != NULL);
+ assert(config_timer != NULL);
- alarm_cancel(alarm_timer);
+ alarm_cancel(config_timer);
+ btif_config_write(0, NULL);
- btif_config_write();
+ pthread_mutex_lock(&lock);
+ config_save(config, CONFIG_FILE_PATH);
+ pthread_mutex_unlock(&lock);
}
-int btif_config_clear(void){
+bool btif_config_clear(void){
assert(config != NULL);
- assert(alarm_timer != NULL);
+ assert(config_timer != NULL);
- alarm_cancel(alarm_timer);
+ alarm_cancel(config_timer);
pthread_mutex_lock(&lock);
config_free(config);
return false;
}
- int ret = config_save(config, CONFIG_FILE_PATH);
+ bool ret = config_save(config, CONFIG_FILE_PATH);
+ btif_config_source = RESET;
pthread_mutex_unlock(&lock);
return ret;
}
static void timer_config_save_cb(UNUSED_ATTR void *data) {
- btif_config_write();
+ // Moving file I/O to btif context instead of timer callback because
+ // it usually takes a lot of time to be completed, introducing
+ // delays during A2DP playback causing blips or choppiness.
+ btif_transfer_context(btif_config_write, 0, NULL, 0, NULL);
}
-static void btif_config_write(void) {
+static void btif_config_write(UNUSED_ATTR UINT16 event, UNUSED_ATTR char *p_param) {
assert(config != NULL);
- assert(alarm_timer != NULL);
+ assert(config_timer != NULL);
btif_config_devcache_cleanup();
pthread_mutex_lock(&lock);
+ rename(CONFIG_FILE_PATH, CONFIG_BACKUP_PATH);
config_save(config, CONFIG_FILE_PATH);
pthread_mutex_unlock(&lock);
}
}
pthread_mutex_unlock(&lock);
}
+
+void btif_debug_config_dump(int fd) {
+ pthread_mutex_lock(&lock);
+
+ dprintf(fd, "\nBluetooth Config:\n");
+
+ dprintf(fd, " Config Source: ");
+ switch(btif_config_source) {
+ case NOT_LOADED:
+ dprintf(fd, "Not loaded\n");
+ break;
+ case ORIGINAL:
+ dprintf(fd, "Original file\n");
+ break;
+ case BACKUP:
+ dprintf(fd, "Backup file\n");
+ break;
+ case NEW_FILE:
+ dprintf(fd, "New file\n");
+ break;
+ case RESET:
+ dprintf(fd, "Reset file\n");
+ break;
+ }
+
+ pthread_mutex_unlock(&lock);
+}