Add ability to preserve existing snoop log

Currently a stack restart or device reboot will overwrite existing snoop
logs when the stack restarts. This patch adds a new configuration file
parameter "BtSnoopSaveLog" that, if enabled, will cause an existing
snoop log to be renamed to "<snoop_file_name>.last" before a new snoop
log is created.

This will allow for easier debugging of crashes that involve a reboot or
stack restart.

Change-Id: I4f56204d31a6bf2e96058938e8616eb6dee7360b
diff --git a/system/conf/bt_stack.conf b/system/conf/bt_stack.conf
index 2ca20ea..711fe51 100644
--- a/system/conf/bt_stack.conf
+++ b/system/conf/bt_stack.conf
@@ -5,6 +5,9 @@
 # BtSnoop log output file
 BtSnoopFileName=/sdcard/btsnoop_hci.log
 
+# Preserve existing BtSnoop log before overwriting
+BtSnoopSaveLog=false
+
 # Enable trace level reconfiguration function
 # Must be present before any TRC_ trace level settings
 TraceConf=true
diff --git a/system/hci/include/bt_hci_lib.h b/system/hci/include/bt_hci_lib.h
index 261a22c..c9f8cd7 100644
--- a/system/hci/include/bt_hci_lib.h
+++ b/system/hci/include/bt_hci_lib.h
@@ -20,6 +20,7 @@
 #define BT_HCI_LIB_H
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
@@ -187,7 +188,7 @@
     int (*transmit_buf)(TRANSAC transac, char *p_buf, int len);
 
     /** Controls HCI logging on/off */
-    int (*logging)(bt_hc_logging_state_t state, char *p_path);
+    int (*logging)(bt_hc_logging_state_t state, char *p_path, bool save_existing);
 
     /** Closes the interface */
     void  (*cleanup)( void );
diff --git a/system/hci/include/btsnoop.h b/system/hci/include/btsnoop.h
index 5dedf68..83c81071 100644
--- a/system/hci/include/btsnoop.h
+++ b/system/hci/include/btsnoop.h
@@ -4,7 +4,7 @@
 
 #include "bt_hci_bdroid.h"
 
-void btsnoop_open(const char *p_path);
+void btsnoop_open(const char *p_path, const bool save_existing);
 void btsnoop_close(void);
 
 void btsnoop_capture(const HC_BT_HDR *p_buf, bool is_rcvd);
diff --git a/system/hci/src/bt_hci_bdroid.c b/system/hci/src/bt_hci_bdroid.c
index 7a32ef0..4038424 100644
--- a/system/hci/src/bt_hci_bdroid.c
+++ b/system/hci/src/bt_hci_bdroid.c
@@ -427,13 +427,13 @@
 }
 
 /** Controls HCI logging on/off */
-static int logging(bt_hc_logging_state_t state, char *p_path) {
+static int logging(bt_hc_logging_state_t state, char *p_path, bool save_existing) {
   BTHCDBG("logging %d", state);
 
   if (state != BT_HC_LOGGING_ON)
     btsnoop_close();
   else if (p_path != NULL)
-    btsnoop_open(p_path);
+    btsnoop_open(p_path, save_existing);
 
   return BT_HC_STATUS_SUCCESS;
 }
diff --git a/system/hci/src/btsnoop.c b/system/hci/src/btsnoop.c
index e74a0d7..e31af35 100644
--- a/system/hci/src/btsnoop.c
+++ b/system/hci/src/btsnoop.c
@@ -120,7 +120,7 @@
   utils_unlock();
 }
 
-void btsnoop_open(const char *p_path) {
+void btsnoop_open(const char *p_path, const bool save_existing) {
   assert(p_path != NULL);
   assert(*p_path != '\0');
 
@@ -131,6 +131,14 @@
     return;
   }
 
+  if (save_existing)
+  {
+    char fname_backup[266] = {0};
+    strncat(fname_backup, p_path, 255);
+    strcat(fname_backup, ".last");
+    rename(p_path, fname_backup);
+  }
+
   hci_btsnoop_fd = open(p_path,
                         O_WRONLY | O_CREAT | O_TRUNC,
                         S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
diff --git a/system/main/bte_conf.c b/system/main/bte_conf.c
index 45d8933..63ace86 100644
--- a/system/main/bte_conf.c
+++ b/system/main/bte_conf.c
@@ -29,6 +29,7 @@
 // TODO: eliminate these global variables.
 extern char hci_logfile[256];
 extern BOOLEAN hci_logging_enabled;
+extern BOOLEAN hci_save_log;
 extern BOOLEAN trace_conf_enabled;
 void bte_trace_conf_config(const config_t *config);
 
@@ -47,6 +48,7 @@
 
   strlcpy(hci_logfile, config_get_string(config, CONFIG_DEFAULT_SECTION, "BtSnoopFileName", ""), sizeof(hci_logfile));
   hci_logging_enabled = config_get_bool(config, CONFIG_DEFAULT_SECTION, "BtSnoopLogOutput", false);
+  hci_save_log = config_get_bool(config, CONFIG_DEFAULT_SECTION, "BtSnoopSaveLog", false);
   trace_conf_enabled = config_get_bool(config, CONFIG_DEFAULT_SECTION, "TraceConf", false);
 
   bte_trace_conf_config(config);
diff --git a/system/main/bte_main.c b/system/main/bte_main.c
index f1c6897..75cc440 100755
--- a/system/main/bte_main.c
+++ b/system/main/bte_main.c
@@ -82,6 +82,7 @@
 ******************************************************************************/
 BOOLEAN hci_logging_enabled = FALSE;    /* by default, turn hci log off */
 BOOLEAN hci_logging_config = FALSE;    /* configured from bluetooth framework */
+BOOLEAN hci_save_log = FALSE; /* save a copy of the log before starting again */
 char hci_logfile[256] = HCI_LOGGING_FILENAME;
 
 /*******************************************************************************
@@ -266,7 +267,7 @@
         return;
     }
 
-    bt_hc_if->logging(new ? BT_HC_LOGGING_ON : BT_HC_LOGGING_OFF, hci_logfile);
+    bt_hc_if->logging(new ? BT_HC_LOGGING_ON : BT_HC_LOGGING_OFF, hci_logfile, hci_save_log);
 }
 
 /******************************************************************************
@@ -292,7 +293,7 @@
         assert(result == BT_HC_STATUS_SUCCESS);
 
         if (hci_logging_enabled == TRUE || hci_logging_config == TRUE)
-            bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile);
+            bt_hc_if->logging(BT_HC_LOGGING_ON, hci_logfile, hci_save_log);
 
 #if (defined (BT_CLEAN_TURN_ON_DISABLED) && BT_CLEAN_TURN_ON_DISABLED == TRUE)
         APPL_TRACE_DEBUG("%s  Not Turninig Off the BT before Turninig ON", __FUNCTION__);
@@ -338,7 +339,7 @@
     pthread_mutex_lock(&cleanup_lock);
 
     if (hci_logging_enabled == TRUE ||  hci_logging_config == TRUE)
-        bt_hc_if->logging(BT_HC_LOGGING_OFF, hci_logfile);
+        bt_hc_if->logging(BT_HC_LOGGING_OFF, hci_logfile, hci_save_log);
     bt_hc_if->cleanup();
 
     pthread_mutex_unlock(&cleanup_lock);