summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhaohuang <haohuang@codeaurora.org>2019-09-16 16:03:09 +0800
committerhaohuang <haohuang@codeaurora.org>2019-11-29 16:28:04 +0800
commitd71529af0f5b103cdbe2679148bd7268cb4713b8 (patch)
tree37acfdeb4fb01c87982bbd8b18f168898bd5f4f2
parenta43430218337739c0c1143dc55474d1036d50558 (diff)
downloadgps-d71529af0f5b103cdbe2679148bd7268cb4713b8.tar.gz
Logging buffer implemented by skip list
Use skip list to implement a log buffer, log sentences will be inserted into this buffer once the log print function is called. the buffer will be dumped when GNSS process crash/killed or send SIGUSR1 signal manually. Change-Id: I5e23cdf30c263fa59108070c9dbfd95c49c2e9b6 CRs-Fixed: 2571326
-rw-r--r--etc/gps.conf21
-rw-r--r--utils/Android.mk3
-rw-r--r--utils/LogBuffer.cpp167
-rw-r--r--utils/LogBuffer.h95
-rw-r--r--utils/Makefile.am2
-rw-r--r--utils/SkipList.h158
-rw-r--r--utils/loc_cfg.cpp10
-rw-r--r--utils/loc_log.cpp50
-rw-r--r--utils/log_util.h62
-rw-r--r--utils/msg_q.c2
10 files changed, 530 insertions, 40 deletions
diff --git a/etc/gps.conf b/etc/gps.conf
index 47aa8ef..1d4e233 100644
--- a/etc/gps.conf
+++ b/etc/gps.conf
@@ -322,3 +322,24 @@ CP_MTLR_ES=0
# and QCSR SS5 hardware receiver.
# By default QTI GNSS receiver is enabled.
# GNSS_DEPLOYMENT = 0
+
+##################################################
+## LOG BUFFER CONFIGURATION
+##################################################
+#LOG_BUFFER_ENABLED, 1=enable, 0=disable
+#*_LEVEL_TIME_DEPTH, maximum time depth of level *
+#in log buffer, unit is second
+#*_LEVEL_MAX_CAPACITY, maximum numbers of level *
+#log print sentences in log buffer
+LOG_BUFFER_ENABLED = 0
+E_LEVEL_TIME_DEPTH = 600
+E_LEVEL_MAX_CAPACITY = 50
+W_LEVEL_TIME_DEPTH = 500
+W_LEVEL_MAX_CAPACITY = 100
+I_LEVEL_TIME_DEPTH = 400
+I_LEVEL_MAX_CAPACITY = 200
+D_LEVEL_TIME_DEPTH = 30
+D_LEVEL_MAX_CAPACITY = 300
+V_LEVEL_TIME_DEPTH = 200
+V_LEVEL_MAX_CAPACITY = 400
+
diff --git a/utils/Android.mk b/utils/Android.mk
index 88ad487..57d485d 100644
--- a/utils/Android.mk
+++ b/utils/Android.mk
@@ -27,7 +27,8 @@ LOCAL_SRC_FILES += \
MsgTask.cpp \
loc_misc_utils.cpp \
loc_nmea.cpp \
- LocIpc.cpp
+ LocIpc.cpp \
+ LogBuffer.cpp
# Flag -std=c++11 is not accepted by compiler when LOCAL_CLANG is set to true
LOCAL_CFLAGS += \
diff --git a/utils/LogBuffer.cpp b/utils/LogBuffer.cpp
new file mode 100644
index 0000000..1bb6f0f
--- /dev/null
+++ b/utils/LogBuffer.cpp
@@ -0,0 +1,167 @@
+/* Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "LogBuffer.h"
+#include <utils/Log.h>
+
+#define LOG_TAG "LocSvc_LogBuffer"
+
+namespace loc_util {
+
+LogBuffer* LogBuffer::mInstance;
+struct sigaction LogBuffer::mOriSigAction[NSIG];
+struct sigaction LogBuffer::mNewSigAction;
+mutex LogBuffer::sLock;
+
+LogBuffer* LogBuffer::getInstance() {
+ if (mInstance == nullptr) {
+ lock_guard<mutex> guard(sLock);
+ if (mInstance == nullptr) {
+ mInstance = new LogBuffer();
+ }
+ }
+ return mInstance;
+}
+
+LogBuffer::LogBuffer(): mLogList(TOTAL_LOG_LEVELS),
+ mConfigVec(TOTAL_LOG_LEVELS, ConfigsInLevel(TIME_DEPTH_THRESHOLD_MINIMAL_IN_SEC,
+ MAXIMUM_NUM_IN_LIST, 0)) {
+ loc_param_s_type log_buff_config_table[] =
+ {
+ {"E_LEVEL_TIME_DEPTH", &mConfigVec[0].mTimeDepthThres, NULL, 'n'},
+ {"E_LEVEL_MAX_CAPACITY", &mConfigVec[0].mMaxNumThres, NULL, 'n'},
+ {"W_LEVEL_TIME_DEPTH", &mConfigVec[1].mTimeDepthThres, NULL, 'n'},
+ {"W_LEVEL_MAX_CAPACITY", &mConfigVec[1].mMaxNumThres, NULL, 'n'},
+ {"I_LEVEL_TIME_DEPTH", &mConfigVec[2].mTimeDepthThres, NULL, 'n'},
+ {"I_LEVEL_MAX_CAPACITY", &mConfigVec[2].mMaxNumThres, NULL, 'n'},
+ {"D_LEVEL_TIME_DEPTH", &mConfigVec[3].mTimeDepthThres, NULL, 'n'},
+ {"D_LEVEL_MAX_CAPACITY", &mConfigVec[3].mMaxNumThres, NULL, 'n'},
+ {"V_LEVEL_TIME_DEPTH", &mConfigVec[4].mTimeDepthThres, NULL, 'n'},
+ {"V_LEVEL_MAX_CAPACITY", &mConfigVec[4].mMaxNumThres, NULL, 'n'},
+ };
+ loc_read_conf(LOC_PATH_GPS_CONF_STR, log_buff_config_table,
+ sizeof(log_buff_config_table)/sizeof(log_buff_config_table[0]));
+ registerSignalHandler();
+}
+
+void LogBuffer::append(string& data, int level, uint64_t timestamp) {
+ lock_guard<mutex> guard(mLock);
+ pair<uint64_t, string> item(timestamp, data);
+ mLogList.append(item, level);
+ mConfigVec[level].mCurrentSize++;
+
+ while ((timestamp - mLogList.front(level).first) > mConfigVec[level].mTimeDepthThres ||
+ mConfigVec[level].mCurrentSize > mConfigVec[level].mMaxNumThres) {
+ mLogList.pop(level);
+ mConfigVec[level].mCurrentSize--;
+ }
+}
+
+//Dump the log buffer of specific level, level = -1 to dump all the levels in log buffer.
+void LogBuffer::dump(std::function<void(stringstream&)> log, int level) {
+ lock_guard<mutex> guard(mLock);
+ list<pair<pair<uint64_t, string>, int>> li;
+ if (-1 == level) {
+ li = mLogList.dump();
+ } else {
+ li = mLogList.dump(level);
+ }
+ ALOGE("Begining of dump, buffer size: %d", (int)li.size());
+ stringstream ln;
+ ln << "dump log buffer, level[" << level << "]" << ", buffer size: " << li.size() << endl;
+ log(ln);
+ for_each (li.begin(), li.end(), [&, this](const pair<pair<uint64_t, string>, int> &item){
+ stringstream line;
+ line << "["<<item.first.first << "] ";
+ line << "Level " << mLevelMap[item.second] << ": ";
+ line << item.first.second << endl;
+ if (log != nullptr) {
+ log(line);
+ }
+ });
+ ALOGE("End of dump");
+}
+
+void LogBuffer::dumpToAdbLogcat() {
+ dump([](stringstream& line){
+ ALOGE("%s", line.str().c_str());
+ });
+}
+
+void LogBuffer::dumpToLogFile(string filePath) {
+ ALOGE("Dump GPS log buffer to file: %s", filePath.c_str());
+ fstream s;
+ s.open(filePath, std::fstream::out | std::fstream::app);
+ dump([&s](stringstream& line){
+ s << line.str();
+ });
+ s.close();
+}
+
+void LogBuffer::flush() {
+ mLogList.flush();
+}
+
+void LogBuffer::registerSignalHandler() {
+ ALOGE("Singal handler registered");
+ mNewSigAction.sa_sigaction = &LogBuffer::signalHandler;
+ mNewSigAction.sa_flags = SA_SIGINFO;
+ sigemptyset(&mNewSigAction.sa_mask);
+
+ sigaction(SIGINT, &mNewSigAction, &mOriSigAction[SIGINT]);
+ sigaction(SIGKILL, &mNewSigAction, &mOriSigAction[SIGKILL]);
+ sigaction(SIGSEGV, &mNewSigAction, &mOriSigAction[SIGSEGV]);
+ sigaction(SIGABRT, &mNewSigAction, &mOriSigAction[SIGABRT]);
+ sigaction(SIGTRAP, &mNewSigAction, &mOriSigAction[SIGTRAP]);
+ sigaction(SIGUSR1, &mNewSigAction, &mOriSigAction[SIGUSR1]);
+}
+
+void LogBuffer::signalHandler(const int code, siginfo_t *const si, void *const sc) {
+ ALOGE("[Gnss Log buffer]Singal handler, signal ID: %d", code);
+
+ //Dump the log buffer to adb logcat
+ mInstance->dumpToAdbLogcat();
+
+ //Dump the log buffer to file
+ time_t now = time(NULL);
+ struct tm *curr_time = localtime(&now);
+ char path[50];
+ snprintf(path, 50, LOG_BUFFER_FILE_PATH "gpslog_%d%d%d-%d%d%d.log",
+ (1900 + curr_time->tm_year), ( 1 + curr_time->tm_mon), curr_time->tm_mday,
+ curr_time->tm_hour, curr_time->tm_min, curr_time->tm_sec);
+
+ mInstance->dumpToLogFile(path);
+
+ //Process won't be terminated if SIGUSR1 is recieved
+ if (code != SIGUSR1) {
+ mOriSigAction[code].sa_sigaction(code, si, sc);
+ }
+}
+
+}
diff --git a/utils/LogBuffer.h b/utils/LogBuffer.h
new file mode 100644
index 0000000..8d90439
--- /dev/null
+++ b/utils/LogBuffer.h
@@ -0,0 +1,95 @@
+/* Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOG_BUFFER_H
+#define LOG_BUFFER_H
+
+#include "SkipList.h"
+#include "log_util.h"
+#include <loc_cfg.h>
+#include <loc_pla.h>
+#include <string>
+#include <sstream>
+#include <ostream>
+#include <fstream>
+#include <time.h>
+#include <mutex>
+#include <signal.h>
+#include <thread>
+#include <functional>
+
+//default error level time depth threshold,
+#define TIME_DEPTH_THRESHOLD_MINIMAL_IN_SEC 60
+//default maximum log buffer size
+#define MAXIMUM_NUM_IN_LIST 50
+//file path of dumped log buffer
+#define LOG_BUFFER_FILE_PATH "/data/vendor/location/"
+
+namespace loc_util {
+
+class ConfigsInLevel{
+public:
+ uint32_t mTimeDepthThres;
+ uint32_t mMaxNumThres;
+ int mCurrentSize;
+
+ ConfigsInLevel(uint32_t time, int num, int size):
+ mTimeDepthThres(time), mMaxNumThres(num), mCurrentSize(size) {}
+};
+
+class LogBuffer {
+private:
+ static LogBuffer* mInstance;
+ static struct sigaction mOriSigAction[NSIG];
+ static struct sigaction mNewSigAction;
+ static mutex sLock;
+
+ SkipList<pair<uint64_t, string>> mLogList;
+ vector<ConfigsInLevel> mConfigVec;
+ mutex mLock;
+
+ const vector<string> mLevelMap {"E", "W", "I", "D", "V"};
+
+public:
+ static LogBuffer* getInstance();
+ void append(string& data, int level, uint64_t timestamp);
+ void dump(std::function<void(stringstream&)> log, int level = -1);
+ void dumpToAdbLogcat();
+ void dumpToLogFile(string filePath);
+ void flush();
+private:
+ LogBuffer();
+ void registerSignalHandler();
+ static void signalHandler(const int code, siginfo_t *const si, void *const sc);
+
+};
+
+}
+
+#endif
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 9a9c67e..72c7872 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -23,6 +23,7 @@ libgps_utils_la_h_sources = \
LocThread.h \
LocTimer.h \
LocIpc.h \
+ SkipList.h\
loc_misc_utils.h \
loc_nmea.h \
gps_extended_c.h \
@@ -42,6 +43,7 @@ libgps_utils_la_c_sources = \
LocTimer.cpp \
LocThread.cpp \
LocIpc.cpp \
+ LogBuffer.cpp \
MsgTask.cpp \
loc_misc_utils.cpp \
loc_nmea.cpp
diff --git a/utils/SkipList.h b/utils/SkipList.h
new file mode 100644
index 0000000..afaa1a6
--- /dev/null
+++ b/utils/SkipList.h
@@ -0,0 +1,158 @@
+/* Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation, nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef LOC_SKIP_LIST_H
+#define LOC_SKIP_LIST_H
+
+#include <stdlib.h>
+#include <list>
+#include <vector>
+#include <iostream>
+#include <algorithm>
+
+using namespace std;
+
+namespace loc_util {
+
+template <typename T,
+ template<typename elem, typename Allocator = std::allocator<elem>> class container = list>
+class SkipNode {
+public:
+ typedef typename container<SkipNode<T, container>>::iterator NodeIterator;
+
+ int mLevel;
+ T mData;
+ NodeIterator mNextInLevel;
+
+ SkipNode(int level, T& data): mLevel(level), mData(data) {}
+};
+
+template <typename T>
+class SkipList {
+ using NodeIterator = typename SkipNode<T>::NodeIterator;
+private:
+ list<SkipNode<T>> mMainList;
+ vector<NodeIterator> mHeadVec;
+ vector<NodeIterator> mTailVec;
+public:
+ SkipList(int totalLevels);
+ void append(T& data, int level);
+ void pop(int level);
+ void pop();
+ T front(int level);
+ int size();
+ void flush();
+ list<pair<T, int>> dump();
+ list<pair<T, int>> dump(int level);
+};
+
+template <typename T>
+SkipList<T>::SkipList(int totalLevels): mHeadVec(totalLevels, mMainList.end()),
+ mTailVec(totalLevels, mMainList.end()) {}
+
+template <typename T>
+void SkipList<T>::append(T& data, int level) {
+ if ( level < 0 || level >= mHeadVec.size()) {
+ return;
+ }
+
+ SkipNode<T> node(level, data);
+ node.mNextInLevel = mMainList.end();
+ mMainList.push_back(node);
+ auto iter = --mMainList.end();
+ if (mHeadVec[level] == mMainList.end()) {
+ mHeadVec[level] = iter;
+ } else {
+ (*mTailVec[level]).mNextInLevel = iter;
+ }
+ mTailVec[level] = iter;
+}
+
+template <typename T>
+void SkipList<T>::pop(int level) {
+ if (mHeadVec[level] == mMainList.end()) {
+ return;
+ }
+
+ if ((*mHeadVec[level]).mNextInLevel == mMainList.end()) {
+ mTailVec[level] = mMainList.end();
+ }
+
+ auto tmp_iter = (*mHeadVec[level]).mNextInLevel;
+ mMainList.erase(mHeadVec[level]);
+ mHeadVec[level] = tmp_iter;
+}
+
+template <typename T>
+void SkipList<T>::pop() {
+ pop(mMainList.front().mLevel);
+}
+
+template <typename T>
+T SkipList<T>::front(int level) {
+ return (*mHeadVec[level]).mData;
+}
+
+template <typename T>
+int SkipList<T>::size() {
+ return mMainList.size();
+}
+
+template <typename T>
+void SkipList<T>::flush() {
+ mMainList.clear();
+ for (int i = 0; i < mHeadVec.size(); i++) {
+ mHeadVec[i] = mMainList.end();
+ mTailVec[i] = mMainList.end();
+ }
+}
+
+template <typename T>
+list<pair<T, int>> SkipList<T>::dump() {
+ list<pair<T, int>> li;
+ for_each(mMainList.begin(), mMainList.end(), [&](SkipNode<T> &item) {
+ li.push_back(make_pair(item.mData, item.mLevel));
+ });
+ return li;
+}
+
+template <typename T>
+list<pair<T, int>> SkipList<T>::dump(int level) {
+ list<pair<T, int>> li;
+ auto head = mHeadVec[level];
+ while (head != mMainList.end()) {
+ li.push_back(make_pair((*head).mData, (*head).mLevel));
+ head = (*head).mNextInLevel;
+ }
+ return li;
+}
+
+}
+
+#endif
diff --git a/utils/loc_cfg.cpp b/utils/loc_cfg.cpp
index 8baf8ca..432095e 100644
--- a/utils/loc_cfg.cpp
+++ b/utils/loc_cfg.cpp
@@ -59,13 +59,15 @@ static uint32_t DEBUG_LEVEL = 0xff;
static uint32_t TIMESTAMP = 0;
static uint32_t DATUM_TYPE = 0;
static bool sVendorEnhanced = true;
+static uint32_t sLogBufferEnabled = 0;
/* Parameter spec table */
static const loc_param_s_type loc_param_table[] =
{
- {"DEBUG_LEVEL", &DEBUG_LEVEL, NULL, 'n'},
- {"TIMESTAMP", &TIMESTAMP, NULL, 'n'},
- {"DATUM_TYPE", &DATUM_TYPE, NULL, 'n'},
+ {"DEBUG_LEVEL", &DEBUG_LEVEL, NULL, 'n'},
+ {"TIMESTAMP", &TIMESTAMP, NULL, 'n'},
+ {"DATUM_TYPE", &DATUM_TYPE, NULL, 'n'},
+ {"LOG_BUFFER_ENABLED", &sLogBufferEnabled, NULL, 'n'},
};
static const int loc_param_num = sizeof(loc_param_table) / sizeof(loc_param_s_type);
@@ -429,6 +431,7 @@ void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_ta
{
FILE *conf_fp = NULL;
+ log_buffer_init(false);
if((conf_fp = fopen(conf_file_name, "r")) != NULL)
{
LOC_LOGD("%s: using %s", __FUNCTION__, conf_file_name);
@@ -441,6 +444,7 @@ void loc_read_conf(const char* conf_file_name, const loc_param_s_type* config_ta
}
/* Initialize logging mechanism with parsed data */
loc_logger_init(DEBUG_LEVEL, TIMESTAMP);
+ log_buffer_init(sLogBufferEnabled);
}
/*=============================================================================
diff --git a/utils/loc_log.cpp b/utils/loc_log.cpp
index ab28998..2c6a3fa 100644
--- a/utils/loc_log.cpp
+++ b/utils/loc_log.cpp
@@ -31,11 +31,13 @@
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <sys/time.h>
#include "log_util.h"
#include "loc_log.h"
#include "msg_q.h"
#include <loc_pla.h>
+#include "LogBuffer.h"
#define BUFFER_SIZE 120
@@ -179,35 +181,6 @@ char *loc_get_time(char *time_string, size_t buf_size)
return time_string;
}
-
-/*===========================================================================
-FUNCTION loc_logger_init
-
-DESCRIPTION
- Initializes the state of DEBUG_LEVEL and TIMESTAMP
-
-DEPENDENCIES
- N/A
-
-RETURN VALUE
- None
-
-SIDE EFFECTS
- N/A
-===========================================================================*/
-void loc_logger_init(unsigned long debug, unsigned long timestamp)
-{
- loc_logger.DEBUG_LEVEL = debug;
-#ifdef TARGET_BUILD_VARIANT_USER
- // force user builds to 2 or less
- if (loc_logger.DEBUG_LEVEL > 2) {
- loc_logger.DEBUG_LEVEL = 2;
- }
-#endif
- loc_logger.TIMESTAMP = timestamp;
-}
-
-
/*===========================================================================
FUNCTION get_timestamp
@@ -236,3 +209,22 @@ char * get_timestamp(char *str, unsigned long buf_size)
return str;
}
+/*===========================================================================
+
+FUNCTION log_buffer_insert
+
+DESCRIPTION
+ Insert a log sentence with specific level to the log buffer.
+
+RETURN VALUE
+ N/A
+
+===========================================================================*/
+void log_buffer_insert(char *str, unsigned long buf_size, int level)
+{
+ timespec tv;
+ clock_gettime(CLOCK_BOOTTIME, &tv);
+ uint64_t elapsedTime = (uint64_t)tv.tv_sec + (uint64_t)tv.tv_nsec/1000000000;
+ string ss = str;
+ loc_util::LogBuffer::getInstance()->append(ss, level, elapsedTime);
+}
diff --git a/utils/log_util.h b/utils/log_util.h
index 192baeb..13c08bc 100644
--- a/utils/log_util.h
+++ b/utils/log_util.h
@@ -30,9 +30,13 @@
#ifndef __LOG_UTIL_H__
#define __LOG_UTIL_H__
+#include <stdbool.h>
+
#if defined (USE_ANDROID_LOGGING) || defined (ANDROID)
// Android and LE targets with logcat support
#include <utils/Log.h>
+#include <unistd.h>
+#include <sys/syscall.h>
#elif defined (USE_GLIB)
// LE targets with no logcat support
@@ -41,6 +45,7 @@
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
+#include <sys/syscall.h>
#ifndef LOG_TAG
#define LOG_TAG "GPS_UTILS"
@@ -90,18 +95,20 @@ typedef struct loc_logger_s
{
unsigned long DEBUG_LEVEL;
unsigned long TIMESTAMP;
+ bool LOG_BUFFER_ENABLE;
} loc_logger_s_type;
+
/*=============================================================================
*
* EXTERNAL DATA
*
*============================================================================*/
-extern loc_logger_s_type loc_logger;
// Logging Improvements
extern const char *loc_logger_boolStr[];
+extern loc_logger_s_type loc_logger;
extern const char *boolStr[];
extern const char VOID_RET[];
extern const char FROM_AFW[];
@@ -117,8 +124,49 @@ extern const char EXIT_ERROR_TAG[];
* MODULE EXPORTED FUNCTIONS
*
*============================================================================*/
-extern void loc_logger_init(unsigned long debug, unsigned long timestamp);
+inline void loc_logger_init(unsigned long debug, unsigned long timestamp)
+{
+ loc_logger.DEBUG_LEVEL = debug;
+#ifdef TARGET_BUILD_VARIANT_USER
+ // force user builds to 2 or less
+ if (loc_logger.DEBUG_LEVEL > 2) {
+ loc_logger.DEBUG_LEVEL = 2;
+ }
+#endif
+ loc_logger.TIMESTAMP = timestamp;
+}
+
+inline void log_buffer_init(bool enabled) {
+ loc_logger.LOG_BUFFER_ENABLE = enabled;
+}
+
extern char* get_timestamp(char* str, unsigned long buf_size);
+extern void log_buffer_insert(char *str, unsigned long buf_size, int level);
+
+/*=============================================================================
+ *
+ * LOGGING BUFFER MACROS
+ *
+ *============================================================================*/
+#ifndef LOG_NDEBUG
+#define LOG_NDEBUG 0
+#endif
+#define TOTAL_LOG_LEVELS 5
+#define LOGGING_BUFFER_MAX_LEN 1024
+#define IF_LOG_BUFFER_ENABLE if (loc_logger.LOG_BUFFER_ENABLE)
+#define INSERT_BUFFER(flag, level, format, x...) \
+{ \
+ IF_LOG_BUFFER_ENABLE { \
+ if (flag == 0) { \
+ char timestr[32]; \
+ get_timestamp(timestr, sizeof(timestr)); \
+ char log_str[LOGGING_BUFFER_MAX_LEN]; \
+ snprintf(log_str, LOGGING_BUFFER_MAX_LEN, "%s %d %ld %s :" format "\n", \
+ timestr, getpid(), syscall(SYS_gettid), LOG_TAG==NULL ? "": LOG_TAG, ##x);\
+ log_buffer_insert(log_str, sizeof(log_str), level); \
+ } \
+ } \
+}
#ifndef DEBUG_DMN_LOC_API
@@ -133,11 +181,11 @@ extern char* get_timestamp(char* str, unsigned long buf_size);
#define IF_LOC_LOGD if((loc_logger.DEBUG_LEVEL >= 4) && (loc_logger.DEBUG_LEVEL <= 5))
#define IF_LOC_LOGV if((loc_logger.DEBUG_LEVEL >= 5) && (loc_logger.DEBUG_LEVEL <= 5))
-#define LOC_LOGE(...) IF_LOC_LOGE { ALOGE(__VA_ARGS__); }
-#define LOC_LOGW(...) IF_LOC_LOGW { ALOGW(__VA_ARGS__); }
-#define LOC_LOGI(...) IF_LOC_LOGI { ALOGI(__VA_ARGS__); }
-#define LOC_LOGD(...) IF_LOC_LOGD { ALOGD(__VA_ARGS__); }
-#define LOC_LOGV(...) IF_LOC_LOGV { ALOGV(__VA_ARGS__); }
+#define LOC_LOGE(...) IF_LOC_LOGE { ALOGE(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 0, __VA_ARGS__);}
+#define LOC_LOGW(...) IF_LOC_LOGW { ALOGW(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 1, __VA_ARGS__);}
+#define LOC_LOGI(...) IF_LOC_LOGI { ALOGI(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 2, __VA_ARGS__);}
+#define LOC_LOGD(...) IF_LOC_LOGD { ALOGD(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 3, __VA_ARGS__);}
+#define LOC_LOGV(...) IF_LOC_LOGV { ALOGV(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 4, __VA_ARGS__);}
#else /* DEBUG_DMN_LOC_API */
diff --git a/utils/msg_q.c b/utils/msg_q.c
index 2d49b4a..3383960 100644
--- a/utils/msg_q.c
+++ b/utils/msg_q.c
@@ -26,6 +26,8 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+// Uncomment to log verbose logs
+#define LOG_NDEBUG 1
#define LOG_TAG "LocSvc_utils_q"
#include <stdio.h>
#include <stdlib.h>