Bring back support for legacy bt_config.xml

If a device migrates directly from L or earlier to a version using this
new implementation, all bt_config will be lost, requiring to repair to
the devices.

Change-Id: Ifdca0d8cad8efaa9f503ca40ac0725547a06f15c
diff --git a/README.md b/README.md
index 23b9d9c..f302fda 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,7 @@
 git clone https://github.com/google/googletest.git
 git clone https://android.googlesource.com/platform/external/libchrome
 git clone https://android.googlesource.com/platform/external/modp_b64
+git clone https://android.googlesource.com/platform/external/tinyxml2
 ```
 
 And third party dependencies of third party dependencies:
diff --git a/btif/Android.mk b/btif/Android.mk
index 6628766..78a475b 100644
--- a/btif/Android.mk
+++ b/btif/Android.mk
@@ -30,6 +30,7 @@
   src/btif_av.c \
   src/btif_avrcp_audio_track.cpp \
   src/btif_config.c \
+  src/btif_config_transcode.cpp \
   src/btif_core.c \
   src/btif_debug.c \
   src/btif_debug_btsnoop.c \
@@ -105,6 +106,7 @@
   $(LOCAL_PATH)/../audio_a2dp_hw \
   $(LOCAL_PATH)/../utils/include \
   $(bluetooth_C_INCLUDES) \
+  external/tinyxml2 \
   external/zlib
 
 # libbtif static library for target
diff --git a/btif/BUILD.gn b/btif/BUILD.gn
index d7171b0..f0d3ef8 100644
--- a/btif/BUILD.gn
+++ b/btif/BUILD.gn
@@ -80,6 +80,7 @@
     "//stack/a2dp",
     "//stack/btm",
     "//stack/include",
+    "//third_party/tinyxml2",
     "//include",
     "//udrv/include",
     "//utils/include",
diff --git a/btif/include/btif_config_transcode.h b/btif/include/btif_config_transcode.h
new file mode 100644
index 0000000..e020ba6
--- /dev/null
+++ b/btif/include/btif_config_transcode.h
@@ -0,0 +1,23 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+typedef struct config_t config_t;
+
+config_t *btif_config_transcode(const char *xml_filename);
diff --git a/btif/src/btif_config.c b/btif/src/btif_config.c
index 82c6069..ef90f89 100644
--- a/btif/src/btif_config.c
+++ b/btif/src/btif_config.c
@@ -32,6 +32,7 @@
 #include "btcore/include/module.h"
 #include "btif_common.h"
 #include "btif_config.h"
+#include "btif_config_transcode.h"
 #include "btif_util.h"
 #include "osi/include/alarm.h"
 #include "osi/include/allocator.h"
@@ -53,9 +54,11 @@
 #if defined(OS_GENERIC)
 static const char *CONFIG_FILE_PATH = "bt_config.conf";
 static const char *CONFIG_BACKUP_PATH = "bt_config.bak";
+static const char *CONFIG_LEGACY_FILE_PATH = "bt_config.xml";
 #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";
+static const char *CONFIG_LEGACY_FILE_PATH = "/data/misc/bluedroid/bt_config.xml";
 #endif  // defined(OS_GENERIC)
 static const period_ms_t CONFIG_SETTLE_PERIOD_MS = 3000;
 
@@ -69,6 +72,7 @@
   NOT_LOADED,
   ORIGINAL,
   BACKUP,
+  LEGACY,
   NEW_FILE,
   RESET
 } btif_config_source = NOT_LOADED;
@@ -127,19 +131,24 @@
   config = config_new(CONFIG_FILE_PATH);
   btif_config_source = ORIGINAL;
   if (!config) {
-    LOG_WARN(LOG_TAG, "%s unable to load config file: %s; using backup.",
+    LOG_WARN("%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_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) {
+    LOG_WARN("%s unable to load backup; attempting to transcode legacy file.", __func__);
+    config = btif_config_transcode(CONFIG_LEGACY_FILE_PATH);
+    btif_config_source = LEGACY;
+  }
+  if (!config) {
+    LOG_ERROR("%s unable to transcode legacy file; creating empty config.", __func__);
+    config = config_new_empty();
+    btif_config_source = NEW_FILE;
+  }
+  if (!config) {
+    LOG_ERROR("%s unable to allocate a config object.", __func__);
+    goto error;
   }
 
   btif_config_devcache_cleanup();
@@ -161,6 +170,7 @@
   pthread_mutex_destroy(&lock);
   config_timer = NULL;
   config = NULL;
+  btif_config_source = NOT_LOADED;
   return future_new_immediate(FUTURE_FAIL);
 }
 
@@ -487,6 +497,9 @@
         case BACKUP:
             dprintf(fd, "Backup file\n");
             break;
+        case LEGACY:
+            dprintf(fd, "Legacy file\n");
+            break;
         case NEW_FILE:
             dprintf(fd, "New file\n");
             break;
diff --git a/btif/src/btif_config_transcode.cpp b/btif/src/btif_config_transcode.cpp
new file mode 100644
index 0000000..e9d859e
--- /dev/null
+++ b/btif/src/btif_config_transcode.cpp
@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#define LOG_TAG "bt_btif_config_transcode"
+
+#include <tinyxml2.h>
+
+extern "C" {
+#include "osi/include/config.h"
+#include "osi/include/log.h"
+}
+
+using namespace tinyxml2;
+
+extern "C" config_t *btif_config_transcode(const char *xml_filename) {
+  XMLDocument document;
+  int error = document.LoadFile(xml_filename);
+  if (error != XML_SUCCESS) {
+    LOG_ERROR("%s unable to load XML file '%s': %d", __func__, xml_filename, error);
+    return NULL;
+  }
+
+  XMLElement *rootElement = document.RootElement();
+  if (!rootElement) {
+    LOG_ERROR("%s unable to find root element; assuming corrupted config file.", __func__);
+    return NULL;
+  }
+
+  config_t *config = config_new_empty();
+  if (!config) {
+    LOG_ERROR("%s unable to allocate config object.", __func__);
+    return NULL;
+  }
+
+  for (XMLElement *i = rootElement->FirstChildElement(); i != NULL; i = i->NextSiblingElement())
+    for (XMLElement *j = i->FirstChildElement(); j != NULL; j = j->NextSiblingElement()) {
+      const char *section = j->Attribute("Tag");
+      for (XMLElement *k = j->FirstChildElement(); k != NULL; k = k->NextSiblingElement()) {
+        const char *key = k->Attribute("Tag");
+        const char *value = k->GetText();
+        if (section && key && value)
+          config_set_string(config, section, key, value);
+      }
+    }
+
+  return config;
+}
diff --git a/doc/style_guide.md b/doc/style_guide.md
index c424a27..9a83206 100644
--- a/doc/style_guide.md
+++ b/doc/style_guide.md
@@ -70,7 +70,9 @@
 Although C++ offers constructs that may make Fluoride development faster,
 safer, more pleasant, etc. the decision _for the time being_ is to stick with
 pure C99. The exceptions are when linking against libraries that are written
-in C++. At the time of writing the library used is `gtest`,
+in C++. At the time of writing these libraries are `gtest` and `tinyxml2`,
+where the latter is a dependency that should be eliminated in favor of simpler,
+non-XML formats.
 
 ### Variadic functions
 Variadic functions are dangerous and should be avoided for most code. The
diff --git a/main/Android.mk b/main/Android.mk
index 303f395..7fb545e 100644
--- a/main/Android.mk
+++ b/main/Android.mk
@@ -52,6 +52,7 @@
 	$(LOCAL_PATH)/../audio_a2dp_hw \
 	$(LOCAL_PATH)/../utils/include \
 	$(bluetooth_C_INCLUDES) \
+	external/tinyxml2 \
 	external/zlib
 
 LOCAL_SHARED_LIBRARIES := \
@@ -66,6 +67,7 @@
     libchrome
 
 LOCAL_STATIC_LIBRARIES := \
+    libtinyxml2 \
     libbt-qcom_sbc_decoder
 
 LOCAL_WHOLE_STATIC_LIBRARIES := \
diff --git a/main/BUILD.gn b/main/BUILD.gn
index d7d0790..05bcb6f 100644
--- a/main/BUILD.gn
+++ b/main/BUILD.gn
@@ -66,6 +66,7 @@
     "//hci",
     "//osi",
     "//stack",
+    "//third_party/tinyxml2",
     "//udrv",
     "//utils",
   ]