replace common qcom sources with samsung ones
This commit is contained in:
5
qcom/opensource/location/utils/Android.bp
Normal file
5
qcom/opensource/location/utils/Android.bp
Normal file
@@ -0,0 +1,5 @@
|
||||
cc_library_headers {
|
||||
name: "libloc_base_util_headers",
|
||||
vendor: true,
|
||||
export_include_dirs: [".", "base_util", ],
|
||||
}
|
||||
2
qcom/opensource/location/utils/Android.mk
Normal file
2
qcom/opensource/location/utils/Android.mk
Normal file
@@ -0,0 +1,2 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(call all-makefiles-under,$(LOCAL_PATH))
|
||||
38
qcom/opensource/location/utils/base_util/Android.bp
Normal file
38
qcom/opensource/location/utils/base_util/Android.bp
Normal file
@@ -0,0 +1,38 @@
|
||||
cc_library_shared {
|
||||
|
||||
name: "libloc_base_util",
|
||||
vendor: true,
|
||||
owner: "qti",
|
||||
|
||||
cflags: [
|
||||
"-fno-short-enums",
|
||||
] + GNSS_CFLAGS,
|
||||
|
||||
arch: {
|
||||
arm: {
|
||||
cflags: ["-DANDROID_32_BIT_PTR_SUPPORT"],
|
||||
},
|
||||
},
|
||||
|
||||
header_libs: [
|
||||
"libutils_headers",
|
||||
"libloc_base_util_headers",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libsqlite",
|
||||
"libssl",
|
||||
"liblog",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"src/config_file.cpp",
|
||||
"src/log.cpp",
|
||||
"src/memorystream.cpp",
|
||||
"src/nvparam_mgr.cpp",
|
||||
"src/postcard.cpp",
|
||||
"src/sync.cpp",
|
||||
"src/string_routines.cpp",
|
||||
"src/time_routines.cpp",
|
||||
],
|
||||
}
|
||||
9
qcom/opensource/location/utils/base_util/Makefile.am
Normal file
9
qcom/opensource/location/utils/base_util/Makefile.am
Normal file
@@ -0,0 +1,9 @@
|
||||
# Makefile.am for gps loc-base-util
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
SUBDIRS = src
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = loc-base-util.pc
|
||||
EXTRA_DIST = $(pkgconfig_DATA)
|
||||
246
qcom/opensource/location/utils/base_util/array.h
Normal file
246
qcom/opensource/location/utils/base_util/array.h
Normal file
@@ -0,0 +1,246 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Array template
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This component implements an array of any type
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#ifndef __XTRAT_WIFI_ARRAY_H__
|
||||
#define __XTRAT_WIFI_ARRAY_H__
|
||||
|
||||
#include <base_util/log.h>
|
||||
#include <base_util/list.h>
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class Array
|
||||
{
|
||||
private:
|
||||
static const char * const TAG;
|
||||
public:
|
||||
|
||||
typedef T * Iterator;
|
||||
|
||||
Array() :
|
||||
m_pArray(0), m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
Array(const Array<T> & rhs) :
|
||||
m_pArray(0), m_size(0)
|
||||
{
|
||||
(void) operator =(rhs);
|
||||
}
|
||||
|
||||
virtual ~Array()
|
||||
{
|
||||
flush();
|
||||
}
|
||||
|
||||
int setSize(const unsigned int size)
|
||||
{
|
||||
int result = 1;
|
||||
flush();
|
||||
if(size > 0)
|
||||
{
|
||||
m_pArray = new T[size];
|
||||
if(0 != m_pArray)
|
||||
{
|
||||
m_size = size;
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_size = 0;
|
||||
result = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid size
|
||||
result = 3;
|
||||
}
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "set size failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
if(0 != m_pArray)
|
||||
{
|
||||
delete[] m_pArray;
|
||||
m_pArray = 0;
|
||||
}
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
int insert(const List<T> & list)
|
||||
{
|
||||
int result = 1;
|
||||
if(list.getSize() > 0)
|
||||
{
|
||||
unsigned int new_size = m_size + list.getSize();
|
||||
T * pNewArray = new T[new_size];
|
||||
if(0 != pNewArray)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_size; ++i)
|
||||
{
|
||||
pNewArray[i] = m_pArray[i];
|
||||
}
|
||||
|
||||
const SingleListNode<T> * pNode = list.getHead();
|
||||
for (unsigned int j = m_size; j < new_size; ++j)
|
||||
{
|
||||
pNewArray[j] = pNode->getValue();
|
||||
pNode = pNode->getNext();
|
||||
}
|
||||
m_size = new_size;
|
||||
|
||||
if(0 != m_pArray)
|
||||
{
|
||||
delete[] m_pArray;
|
||||
}
|
||||
m_pArray = pNewArray;
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing. it's okay to insert empty list into an array
|
||||
result = 0;
|
||||
}
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "insertion failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
T & operator [](const unsigned int index)
|
||||
{
|
||||
if(index < m_size)
|
||||
{
|
||||
return m_pArray[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "index out of range\n");
|
||||
// could be null reference, but we're doomed anyway
|
||||
return m_pArray[0];
|
||||
}
|
||||
}
|
||||
|
||||
const T & operator [](const unsigned int index) const
|
||||
{
|
||||
if(index < m_size)
|
||||
{
|
||||
return m_pArray[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "index out of range\n");
|
||||
// could be null reference, but we're doomed anyway
|
||||
return m_pArray[0];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int getSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
const Array<T> & operator =(const Array<T> & rhs)
|
||||
{
|
||||
int result = 1;
|
||||
|
||||
if(&rhs == this)
|
||||
{
|
||||
// do nothing for self-assignment
|
||||
return *this;
|
||||
}
|
||||
|
||||
flush();
|
||||
int new_size = rhs.getSize();
|
||||
|
||||
if(new_size > 0)
|
||||
{
|
||||
|
||||
T * pNewArray = new T[new_size];
|
||||
if(0 != pNewArray)
|
||||
{
|
||||
for (int i = 0; i < new_size; ++i)
|
||||
{
|
||||
pNewArray[i] = rhs.m_pArray[i];
|
||||
}
|
||||
m_size = new_size;
|
||||
|
||||
if(0 != m_pArray)
|
||||
{
|
||||
delete[] m_pArray;
|
||||
}
|
||||
m_pArray = pNewArray;
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing. it's okay to insert empty array into an array
|
||||
result = 0;
|
||||
}
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "assignment failed %d", result);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// used in searching or sorting
|
||||
const T * getRawArray() const
|
||||
{
|
||||
return m_pArray;
|
||||
}
|
||||
T * getRawArray()
|
||||
{
|
||||
return m_pArray;
|
||||
}
|
||||
|
||||
Iterator begin()
|
||||
{
|
||||
return Iterator(m_pArray);
|
||||
}
|
||||
|
||||
Iterator end()
|
||||
{
|
||||
return Iterator(m_pArray + m_size);
|
||||
}
|
||||
|
||||
private:
|
||||
T * m_pArray;
|
||||
unsigned int m_size;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
const char * const Array<T>::TAG = "Array";
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
#endif //#ifndef __XTRAT_WIFI_ARRAY_H__
|
||||
44
qcom/opensource/location/utils/base_util/config_file.h
Normal file
44
qcom/opensource/location/utils/base_util/config_file.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Config file
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This header declares a config file parser
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#ifndef __XTRAT_WIFI_CONFIG_FILE_H__
|
||||
#define __XTRAT_WIFI_CONFIG_FILE_H__
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
class ConfigFile
|
||||
{
|
||||
public:
|
||||
static ConfigFile * createInstance(const char * const filename, const size_t max_line_length = 1023,
|
||||
const bool verbose = false);
|
||||
|
||||
virtual ~ConfigFile() = 0;
|
||||
|
||||
virtual bool loaded() const = 0;
|
||||
|
||||
enum RETURN_CODE
|
||||
{
|
||||
NO_ERROR_RESULT_SET = 0, NOT_FOUND = 1000
|
||||
};
|
||||
|
||||
virtual int getString(const char * const name, const char ** pStr) = 0;
|
||||
virtual int getStringDup(const char * const name, const char ** pStr, const char * const strDefault = 0) = 0;
|
||||
virtual int getInt32(const char * const name, int & value) = 0;
|
||||
virtual int getInt32Default(const char * const name, int & value, const int & Default) = 0;
|
||||
virtual int get_PZ_Int32Default(const char * const name, int & value, const int & Default) = 0;
|
||||
virtual int get_PNZ_Int32Default(const char * const name, int & value, const int & Default) = 0;
|
||||
virtual int getDouble(const char * const name, double & value) = 0;
|
||||
virtual int getDoubleDefault(const char * const name, double & value, const double & Default) = 0;
|
||||
};
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
#endif //#ifndef __XTRAT_WIFI_CONFIG_FILE_H__
|
||||
89
qcom/opensource/location/utils/base_util/configure.ac
Normal file
89
qcom/opensource/location/utils/base_util/configure.ac
Normal file
@@ -0,0 +1,89 @@
|
||||
# configure.ac -- Autoconf script for gps loc-base-util
|
||||
#
|
||||
# Process this file with autoconf to produce a configure script
|
||||
|
||||
# Requires autoconf tool later than 2.61
|
||||
AC_PREREQ(2.61)
|
||||
# Initialize the gps loc-base-util package version 1.0.0
|
||||
AC_INIT([loc-base-util],1.0.0)
|
||||
# Does not strictly follow GNU Coding standards
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||
# Disables auto rebuilding of configure, Makefile.ins
|
||||
AM_MAINTAINER_MODE
|
||||
# Verifies the --srcdir is correct by checking for the path
|
||||
AC_CONFIG_SRCDIR([Makefile.am])
|
||||
# defines some macros variable to be included by source
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_LIBTOOL
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_AWK
|
||||
AC_PROG_CPP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
# Checks for libraries.
|
||||
AC_ARG_WITH([core_includes],
|
||||
AC_HELP_STRING([--with-core-includes=@<:@dir@:>@],
|
||||
[Specify the location of the core headers]),
|
||||
[core_incdir=$withval],
|
||||
with_core_includes=no)
|
||||
|
||||
if test "x$with_core_includes" != "xno"; then
|
||||
CPPFLAGS="${CPPFLAGS} -I${core_incdir}"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([locpla_includes],
|
||||
AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@],
|
||||
[specify the path to locpla-includes in loc-pla_git.bb]),
|
||||
[locpla_incdir=$withval],
|
||||
with_locpla_includes=no)
|
||||
|
||||
if test "x$with_locpla_includes" != "xno"; then
|
||||
AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}")
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([core_includes],
|
||||
AC_HELP_STRING([--with-core-includes=@<:@dir@:>@],
|
||||
[Specify the location of the core headers]),
|
||||
[core_incdir=$withval],
|
||||
with_core_includes=no)
|
||||
|
||||
if test "x$with_core_includes" != "xno"; then
|
||||
CPPFLAGS="${CPPFLAGS} -I${core_incdir}"
|
||||
fi
|
||||
|
||||
AC_SUBST([CPPFLAGS])
|
||||
|
||||
AC_ARG_WITH([glib],
|
||||
AC_HELP_STRING([--with-glib],
|
||||
[enable glib, building HLOS systems which use glib]))
|
||||
|
||||
if (test "x${with_glib}" = "xyes"); then
|
||||
AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib])
|
||||
PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes,
|
||||
AC_MSG_ERROR(GThread >= 2.16 is required))
|
||||
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
|
||||
AC_MSG_ERROR(GLib >= 2.16 is required))
|
||||
GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
|
||||
GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
|
||||
|
||||
AC_SUBST(GLIB_CFLAGS)
|
||||
AC_SUBST(GLIB_LIBS)
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
|
||||
|
||||
AC_CONFIG_FILES([ \
|
||||
Makefile \
|
||||
src/Makefile \
|
||||
loc-base-util.pc
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
541
qcom/opensource/location/utils/base_util/list.h
Normal file
541
qcom/opensource/location/utils/base_util/list.h
Normal file
@@ -0,0 +1,541 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
List template
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This component implements a list of any type
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#ifndef __XTRAT_WIFI_LIST_H__
|
||||
#define __XTRAT_WIFI_LIST_H__
|
||||
|
||||
#include <new>
|
||||
|
||||
// for size_t, qsort
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <base_util/log.h>
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
// the reason we do not use STL/STLport is for portability.
|
||||
// the availability of STL on other linux targets are not clear to
|
||||
// me at this time
|
||||
// also STL may or may not work well with JNI/NDK code for C++ exception
|
||||
|
||||
template<typename T>
|
||||
class SingleListNode
|
||||
{
|
||||
public:
|
||||
SingleListNode(const T & rhs) :
|
||||
m_pNext(0), m_value(rhs)
|
||||
{
|
||||
}
|
||||
|
||||
inline const SingleListNode<T> * getNext() const
|
||||
{
|
||||
return m_pNext;
|
||||
}
|
||||
|
||||
inline SingleListNode<T> * getNext()
|
||||
{
|
||||
return m_pNext;
|
||||
}
|
||||
|
||||
inline void setNext(SingleListNode<T> * const pNext)
|
||||
{
|
||||
m_pNext = pNext;
|
||||
}
|
||||
|
||||
inline T & getValue()
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
inline const T & getValue() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
inline T * getPointer()
|
||||
{
|
||||
return &m_value;
|
||||
}
|
||||
|
||||
inline const T * getPointer() const
|
||||
{
|
||||
return &m_value;
|
||||
}
|
||||
|
||||
private:
|
||||
SingleListNode<T> * m_pNext;
|
||||
T m_value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class List;
|
||||
|
||||
template<typename T>
|
||||
class ConstListIterator
|
||||
{
|
||||
protected:
|
||||
static const char * const TAG;
|
||||
ConstListIterator(SingleListNode<T> * const pNode) :
|
||||
m_pNode(pNode)
|
||||
{
|
||||
}
|
||||
friend class List<T> ;
|
||||
public:
|
||||
|
||||
typedef T ValueType;
|
||||
|
||||
inline bool operator==(const ConstListIterator & rhs) const
|
||||
{
|
||||
return (m_pNode == rhs.m_pNode);
|
||||
}
|
||||
|
||||
inline bool operator!=(const ConstListIterator & rhs) const
|
||||
{
|
||||
return (m_pNode != rhs.m_pNode);
|
||||
}
|
||||
|
||||
void operator++()
|
||||
{
|
||||
if(0 != m_pNode)
|
||||
{
|
||||
m_pNode = m_pNode->getNext();
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "operator ++ with null iterator");
|
||||
}
|
||||
}
|
||||
|
||||
bool isLastNode()
|
||||
{
|
||||
bool is_last = false;
|
||||
|
||||
if(0 != m_pNode)
|
||||
{
|
||||
if (m_pNode->getNext() == 0)
|
||||
{
|
||||
is_last = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "isLastNode called with null iterator");
|
||||
}
|
||||
|
||||
return is_last;
|
||||
}
|
||||
|
||||
const T& operator*() const
|
||||
{
|
||||
if(0 == m_pNode)
|
||||
{
|
||||
log_error(TAG, "operator * with null iterator");
|
||||
}
|
||||
|
||||
return this->m_pNode->getValue();
|
||||
}
|
||||
|
||||
const T* ptr() const
|
||||
{
|
||||
if(0 == m_pNode)
|
||||
{
|
||||
log_error(TAG, "ptr with null iterator");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_pNode->getPointer();
|
||||
}
|
||||
}
|
||||
|
||||
inline const T* operator->() const
|
||||
{
|
||||
return this->m_pNode->getPointer();
|
||||
}
|
||||
|
||||
protected:
|
||||
SingleListNode<T> * m_pNode;
|
||||
};
|
||||
|
||||
// note: to access any inherited member in a templated base class
|
||||
// we need to either address full class name ::, or add this->
|
||||
// this is new in C++ to avoid parser conflicts
|
||||
template<typename T>
|
||||
class ListIterator : public ConstListIterator<T>
|
||||
{
|
||||
private:
|
||||
ListIterator(SingleListNode<T> * const pNode) :
|
||||
ConstListIterator<T>(pNode)
|
||||
{
|
||||
}
|
||||
friend class List<T> ;
|
||||
public:
|
||||
|
||||
T& operator*() const
|
||||
{
|
||||
if(0 == this->m_pNode)
|
||||
{
|
||||
log_error(this->TAG, "operator * with null iterator");
|
||||
}
|
||||
|
||||
return this->m_pNode->getValue();
|
||||
}
|
||||
|
||||
T* ptr() const
|
||||
{
|
||||
if(0 == this->m_pNode)
|
||||
{
|
||||
log_error(this->TAG, "ptr with null iterator");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->m_pNode->getPointer();
|
||||
}
|
||||
}
|
||||
|
||||
inline T* operator->() const
|
||||
{
|
||||
return this->m_pNode->getPointer();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class List
|
||||
{
|
||||
private:
|
||||
static const char * const TAG;
|
||||
public:
|
||||
|
||||
typedef T ValueType;
|
||||
typedef ListIterator<T> Iterator;
|
||||
typedef ConstListIterator<T> ConstIterator;
|
||||
|
||||
List() :
|
||||
m_pHead(0), m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
int append(const List<T> & rhs)
|
||||
{
|
||||
int result = 0;
|
||||
for (List<T>::ConstIterator it = rhs.begin(); it != rhs.end(); ++it)
|
||||
{
|
||||
if(0 != add_head(*it))
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int append_reverse(const List<T> & rhs)
|
||||
{
|
||||
return append(rhs);
|
||||
}
|
||||
|
||||
virtual ~List()
|
||||
{
|
||||
flush();
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
SingleListNode<T> * pNode = m_pHead;
|
||||
while (0 != pNode)
|
||||
{
|
||||
SingleListNode<T> * pNextNode = pNode->getNext();
|
||||
delete pNode;
|
||||
pNode = pNextNode;
|
||||
}
|
||||
m_size = 0;
|
||||
m_pHead = 0;
|
||||
}
|
||||
|
||||
int add(const T& rhs)
|
||||
{
|
||||
int result = 1;
|
||||
SingleListNode<T> * pNewNode = new SingleListNode<T>(rhs);
|
||||
if(0 != pNewNode)
|
||||
{
|
||||
pNewNode->setNext(m_pHead);
|
||||
m_pHead = pNewNode;
|
||||
++m_size;
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're dead
|
||||
result = 2;
|
||||
}
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "add : failed %d", result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int add_tail (const T& rhs)
|
||||
{
|
||||
int result = 1;
|
||||
SingleListNode<T> * pPrevNode = 0;
|
||||
SingleListNode<T> * pNode = m_pHead;
|
||||
|
||||
SingleListNode<T> * pNewNode = new SingleListNode<T>(rhs);
|
||||
if (0 == pNewNode)
|
||||
{
|
||||
result = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (0 != pNode)
|
||||
{
|
||||
pPrevNode = pNode;
|
||||
pNode = pNode->getNext();
|
||||
}
|
||||
|
||||
if (pPrevNode == 0)
|
||||
{
|
||||
m_pHead = pNewNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
pPrevNode->setNext (pNewNode);
|
||||
}
|
||||
|
||||
++m_size;
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int add_head(const T& rhs)
|
||||
{
|
||||
return add(rhs);
|
||||
}
|
||||
|
||||
int sort(bool reverse = false)
|
||||
{
|
||||
SingleListNode<T> ** nodes = 0;
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(0 >= m_size)
|
||||
{
|
||||
// empty list
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
nodes = new (std::nothrow) SingleListNode<T> *[m_size];
|
||||
if(0 == nodes)
|
||||
{
|
||||
result = 3;
|
||||
break;
|
||||
}
|
||||
// fill the array with null pointers
|
||||
for (size_t i = 0; i < m_size; ++i)
|
||||
{
|
||||
nodes[i] = 0;
|
||||
}
|
||||
|
||||
// create an array of node pointers
|
||||
size_t index = 0;
|
||||
for (SingleListNode<T> * pNode = m_pHead; (pNode != 0) && (index < m_size); pNode = pNode->getNext())
|
||||
{
|
||||
nodes[index] = pNode;
|
||||
++index;
|
||||
}
|
||||
|
||||
if(index != m_size)
|
||||
{
|
||||
// inconsistent size and actual list content
|
||||
result = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!reverse)
|
||||
{
|
||||
qsort(nodes, m_size, sizeof(SingleListNode<T> *), _comparator);
|
||||
}
|
||||
else
|
||||
{
|
||||
qsort(nodes, m_size, sizeof(SingleListNode<T> *), _reverse_comparator);
|
||||
}
|
||||
|
||||
// note we have checked that the list cannot be empty, so node[0] is always defined
|
||||
m_pHead = nodes[0];
|
||||
// note we have checked that the list cannot be empty, so m_size is at least 1
|
||||
for (size_t i = 0; i < (m_size - 1); ++i)
|
||||
{
|
||||
nodes[i]->setNext(nodes[i + 1]);
|
||||
}
|
||||
// note we have checked that the list cannot be empty, so m_size is at least 1
|
||||
nodes[m_size - 1]->setNext(0);
|
||||
|
||||
delete[] nodes;
|
||||
nodes = 0;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != nodes)
|
||||
{
|
||||
delete[] nodes;
|
||||
nodes = 0;
|
||||
}
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "sort : failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int remove(const T& rhs, const bool ok_if_not_found = false)
|
||||
{
|
||||
int result = 1;
|
||||
SingleListNode<T> * pPrevNode = 0;
|
||||
SingleListNode<T> * pNode = m_pHead;
|
||||
|
||||
while (0 != pNode)
|
||||
{
|
||||
if(rhs == pNode->getValue())
|
||||
{
|
||||
if(0 != pPrevNode)
|
||||
{
|
||||
pPrevNode->setNext(pNode->getNext());
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're the head
|
||||
m_pHead = pNode->getNext();
|
||||
}
|
||||
--m_size;
|
||||
delete pNode;
|
||||
pNode = 0;
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
pPrevNode = pNode;
|
||||
pNode = pNode->getNext();
|
||||
}
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
if((1 == result) && ok_if_not_found)
|
||||
{
|
||||
// we couldn't find it, but caller said it's okay
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "remove: failed %d", result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Iterator erase(const Iterator & target)
|
||||
{
|
||||
int result = 1;
|
||||
SingleListNode<T> * pPrevNode = 0;
|
||||
SingleListNode<T> * pNode = m_pHead;
|
||||
SingleListNode<T> * pNextNode = 0;
|
||||
|
||||
while (0 != pNode)
|
||||
{
|
||||
if(target == Iterator(pNode))
|
||||
{
|
||||
pNextNode = pNode->getNext();
|
||||
if(0 != pPrevNode)
|
||||
{
|
||||
pPrevNode->setNext(pNextNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're the head
|
||||
m_pHead = pNextNode;
|
||||
}
|
||||
--m_size;
|
||||
delete pNode;
|
||||
pNode = 0;
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
pPrevNode = pNode;
|
||||
pNode = pNode->getNext();
|
||||
}
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "erase: failed %d", result);
|
||||
}
|
||||
|
||||
return Iterator(pNextNode);
|
||||
}
|
||||
|
||||
inline Iterator begin()
|
||||
{
|
||||
return Iterator(m_pHead);
|
||||
}
|
||||
|
||||
inline Iterator end()
|
||||
{
|
||||
return Iterator(0);
|
||||
}
|
||||
|
||||
inline ConstIterator begin() const
|
||||
{
|
||||
return ConstIterator(m_pHead);
|
||||
}
|
||||
|
||||
inline ConstIterator end() const
|
||||
{
|
||||
return ConstIterator(0);
|
||||
}
|
||||
|
||||
inline size_t getSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
protected:
|
||||
SingleListNode<T> * m_pHead;
|
||||
size_t m_size;
|
||||
|
||||
static int _comparator(const void * lhs, const void * rhs)
|
||||
{
|
||||
const SingleListNode<T> * const left_node = *reinterpret_cast<SingleListNode<T> * const *>(lhs);
|
||||
const SingleListNode<T> * const right_node = *reinterpret_cast<SingleListNode<T> * const *>(rhs);
|
||||
return list_comparator(left_node->getValue(), right_node->getValue());
|
||||
}
|
||||
|
||||
static int _reverse_comparator(const void * lhs, const void * rhs)
|
||||
{
|
||||
return _comparator(rhs, lhs);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
const char * const List<T>::TAG = "List";
|
||||
|
||||
template<typename T>
|
||||
const char * const ConstListIterator<T>::TAG = "List";
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
#endif //#ifndef __XTRAT_WIFI_LIST_H__
|
||||
10
qcom/opensource/location/utils/base_util/loc-base-util.pc.in
Normal file
10
qcom/opensource/location/utils/base_util/loc-base-util.pc.in
Normal file
@@ -0,0 +1,10 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: loc-base-util
|
||||
Description: QTI GPS Loc base utils
|
||||
Version: @VERSION
|
||||
Libs: -L${libdir} -lloc_base_util
|
||||
Cflags: -I${includedir} -I${includedir}/loc-base-util
|
||||
46
qcom/opensource/location/utils/base_util/log.h
Normal file
46
qcom/opensource/location/utils/base_util/log.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Log utility
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This header declares a logging utility
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#ifndef __XTRAT_WIFI_LOG_H__
|
||||
#define __XTRAT_WIFI_LOG_H__
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
enum ERROR_LEVEL
|
||||
{
|
||||
EL_LOG_OFF = 0, EL_ERROR = 1, EL_WARNING = 2, EL_INFO = 3, EL_DEBUG = 4, EL_VERBOSE = 5, EL_LOG_ALL = 100
|
||||
};
|
||||
|
||||
// bits masks for Error Output preference
|
||||
enum ERROR_OUTPUT
|
||||
{
|
||||
EO_ANDROID = 0x1, EO_STDOUT = 0x2, EO_ALL = 0x3
|
||||
};
|
||||
|
||||
void log_error(const char * const local_log_tag, const char * const format, ...);
|
||||
void log_warning(const char * const local_log_tag, const char * const format, ...);
|
||||
void log_info(const char * const local_log_tag, const char * const format, ...);
|
||||
void log_debug(const char * const local_log_tag, const char * const format, ...);
|
||||
void log_verbose(const char * const local_log_tag, const char * const format, ...);
|
||||
|
||||
int log_set_global_level(const ERROR_LEVEL level);
|
||||
int log_set_global_tag(const char * const tag);
|
||||
int log_flush_all_local_level();
|
||||
int log_flush_local_level_for_tag(const char *const tag);
|
||||
|
||||
int log_set_local_level_for_tag(const char *const tag, const ERROR_LEVEL level);
|
||||
int log_set_local_level_for_tag(const char *const tag, const ERROR_LEVEL level,
|
||||
const ERROR_OUTPUT output);
|
||||
bool is_log_verbose_enabled(const char * const local_log_tag);
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
#endif //#ifndef __XTRAT_WIFI_LOG_H__
|
||||
65
qcom/opensource/location/utils/base_util/memorystream.h
Normal file
65
qcom/opensource/location/utils/base_util/memorystream.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Memory stream
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This header declares two memory streams, one for input and one for output
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#ifndef __XTRAT_WIFI_MEMORY_STREAM_H__
|
||||
#define __XTRAT_WIFI_MEMORY_STREAM_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
class MemoryStreamBase
|
||||
{
|
||||
public:
|
||||
virtual ~MemoryStreamBase() = 0;
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
virtual size_t getSize() const = 0;
|
||||
virtual const BYTE * getBuffer() const = 0;
|
||||
};
|
||||
|
||||
class OutMemoryStream: public MemoryStreamBase
|
||||
{
|
||||
public:
|
||||
static OutMemoryStream * createInstance();
|
||||
virtual ~OutMemoryStream() = 0;
|
||||
|
||||
// note: only OutMemoryStream supports the non-const version of getBuffer
|
||||
virtual BYTE * getBufferNonConst() = 0;
|
||||
|
||||
virtual int append(const void * const pData, const size_t length) = 0;
|
||||
virtual size_t getPutCursor() const = 0;
|
||||
};
|
||||
|
||||
class InMemoryStream: public MemoryStreamBase
|
||||
{
|
||||
public:
|
||||
static InMemoryStream * createInstance();
|
||||
|
||||
// take ownership of the memory block from given OutMemoryStream 'os'
|
||||
// after this statement, 'os' is no longer usable, and won't delete the memory block at destruction
|
||||
// instead, this newly created InMemoryStream will have to delete that memory block
|
||||
static InMemoryStream * createInstance(OutMemoryStream * const os);
|
||||
|
||||
virtual ~InMemoryStream() = 0;
|
||||
|
||||
virtual int setBufferOwnership(const void ** const ppIn, const size_t length) = 0;
|
||||
virtual int setBufferNoDup(const void * const pIn, const size_t length) = 0;
|
||||
virtual int extract(void * const pData, const size_t length) = 0;
|
||||
virtual size_t getGetCursor() const = 0;
|
||||
virtual int setGetCursor(const size_t cursor) = 0;
|
||||
virtual size_t getCapacity() const = 0;
|
||||
virtual InMemoryStream * clone() const = 0;
|
||||
};
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
#endif //#ifndef __XTRAT_WIFI_MEMORY_STREAM_H__
|
||||
146
qcom/opensource/location/utils/base_util/nvparam_mgr.h
Normal file
146
qcom/opensource/location/utils/base_util/nvparam_mgr.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
GTP storage manager for persistent parameters
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This declares the public interface of storage manager for
|
||||
permanent parameters.
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#ifndef __XTRAT_WIFI_NVPARAM_MGR_H__
|
||||
#define __XTRAT_WIFI_NVPARAM_MGR_H__
|
||||
#include <stdint.h>
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
// Below is the list of parameter names to be shared among modules
|
||||
// for 32-bit pseudo client ID, this will be 32 bit signed,
|
||||
// for 64 bit signed or unsigned
|
||||
#define PARAM_NAME_PSEUDO_CLIENT_ID "PSEUDO_CLIENT_ID"
|
||||
#define PARAM_NAME_PSEUDO_CLIENT_ID_64BIT "PSEUDO_CLIENT_ID_64BIT"
|
||||
|
||||
// list of error code currently supported by nv param manager
|
||||
// for saveXXXParam and getXXXParam
|
||||
typedef enum
|
||||
{
|
||||
NV_PARAM_ERR_NO_ERR = 0,
|
||||
// the parameter is not available
|
||||
NV_PARAM_ERR_PARAM_NOT_FOUND = 1,
|
||||
NV_PARAM_ERR_PRRAM_NOT_VALID = 2,
|
||||
// sqlite is locked and operation can not be performed now,
|
||||
// if the operation is critical, suggest application to
|
||||
// wait a few seconds and try again.
|
||||
NV_PARAM_ERR_SQLITE_BUSY = 3,
|
||||
// other sqlite error
|
||||
NV_PARAM_ERR_SQLITE_OTHER_ERR = 4,
|
||||
// leave some range for extension
|
||||
NV_PARAM_ERR_OTHER_ERR = 100
|
||||
} nv_param_err_code;
|
||||
|
||||
// NOTE: to use this class, it is user's responsibility to make sure
|
||||
// that nv param name is unique. It is recommended nv param name to
|
||||
// start with your module name to avoid collision.
|
||||
class NvParamMgr
|
||||
{
|
||||
public:
|
||||
// returns singleton NvParamMgr implementation class
|
||||
// NOTE: If the returned poiner is non-NULL, please
|
||||
// call NvParamMgr::releaseInstance after usage.
|
||||
static NvParamMgr* getInstance();
|
||||
// releases the refence to NvParamMgr implementation class
|
||||
// NOTE: calling this function need to be paired when getInstance()
|
||||
// is returning non-NULL pointer.
|
||||
static void releaseInstance();
|
||||
|
||||
// Below APIs are thread safe with current sqlite based implementation.
|
||||
//
|
||||
// The APIs will save the given param value into the permanent storage file.
|
||||
// Return value is defined in nv_param_err_code.
|
||||
//
|
||||
// Note: If returned error code is NV_PARAM_ERR_SQLITE_BUSY, the sqlite file
|
||||
// is locked and operation can not be performed now,
|
||||
// if the operation is critical, suggest application to
|
||||
// wait a few seconds and try again.
|
||||
virtual nv_param_err_code saveInt32Param (const char* param_name,
|
||||
const int param_value) = 0;
|
||||
|
||||
virtual nv_param_err_code saveBoolParam (const char* param_name,
|
||||
const bool param_value) = 0;
|
||||
|
||||
virtual nv_param_err_code saveFloatParam (const char* param_name,
|
||||
const float param_value) = 0;
|
||||
|
||||
virtual nv_param_err_code saveUInt32Param (const char* param_name,
|
||||
const unsigned int param_value) = 0;
|
||||
|
||||
virtual nv_param_err_code saveInt64Param (const char* param_name,
|
||||
const long long param_value) = 0;
|
||||
|
||||
virtual nv_param_err_code saveUInt64Param (const char* param_name,
|
||||
const unsigned long long param_value) = 0;
|
||||
|
||||
virtual nv_param_err_code saveStringParam (const char* param_name,
|
||||
const char* param_value) = 0;
|
||||
|
||||
virtual nv_param_err_code saveBlobParam (const char* param_name,
|
||||
const unsigned char* param_value,
|
||||
unsigned int param_size_in_bytes) = 0;
|
||||
|
||||
// Below APIs are thread safe with current sqlite based implementation.
|
||||
//
|
||||
// The APIs will retrive the given param value from the permanent storage file
|
||||
// If the param can not be retrieved, param_value will not be
|
||||
// modified.
|
||||
//
|
||||
// Return value is defined in nv_param_err_code, 0 for success.
|
||||
//
|
||||
// Note: If returned error code is NV_PARAM_ERR_SQLITE_BUSY,
|
||||
// the sqlite file is locked and operation can not be performed now,
|
||||
// if the operation is critical, suggest application to
|
||||
// wait a few seconds and try again.
|
||||
virtual nv_param_err_code getInt32Param (const char* param_name,
|
||||
int & param_value) = 0;
|
||||
|
||||
virtual nv_param_err_code getBoolParam (const char* param_name,
|
||||
bool & param_value) = 0;
|
||||
|
||||
virtual nv_param_err_code getFloatParam (const char* param_name,
|
||||
float & param_value) = 0;
|
||||
|
||||
virtual nv_param_err_code getUInt32Param (const char* param_name,
|
||||
unsigned int & param_value) = 0;
|
||||
|
||||
virtual nv_param_err_code getInt64Param (const char* param_name,
|
||||
long long & param_value) = 0;
|
||||
|
||||
virtual nv_param_err_code getUInt64Param (const char* param_name,
|
||||
unsigned long long & param_value) = 0;
|
||||
|
||||
// 0 or NV_PARAM_ERR_NO_ERR: when successful
|
||||
// NOTE: memory returned via param_value need to be freed by caller
|
||||
// via delete [] when return code is 0 (NV_PARAM_ERR_NO_ERROR)
|
||||
virtual nv_param_err_code getStringParam (const char* param_name,
|
||||
char* ¶m_value,
|
||||
unsigned int ¶m_size_in_bytes) = 0;
|
||||
|
||||
// 0 or NV_PARAM_ERR_NO_ERR: when successful
|
||||
// NOTE: memory returned via param_value need to be freed by caller
|
||||
// via delete [] when return code is 0 (NV_PARAM_ERR_NO_ERROR)
|
||||
virtual nv_param_err_code getBlobParam (const char* param_name,
|
||||
unsigned char* ¶m_value,
|
||||
unsigned int ¶m_size_in_bytes) = 0;
|
||||
|
||||
protected:
|
||||
// allow constructor to be made only via getInstance
|
||||
NvParamMgr() {};
|
||||
|
||||
// prohibit calling delete on the pointer returned from
|
||||
// NvParamMgr::getInstance()
|
||||
virtual ~NvParamMgr() {};
|
||||
};
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
#endif // #ifndef __XTRAT_WIFI_NVPARAM_MGR_H__
|
||||
158
qcom/opensource/location/utils/base_util/postcard.h
Normal file
158
qcom/opensource/location/utils/base_util/postcard.h
Normal file
@@ -0,0 +1,158 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
IPC message
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This header declares two IPC messages, one for input and one for output
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#ifndef __XTRAT_WIFI_POSTCARD_H__
|
||||
#define __XTRAT_WIFI_POSTCARD_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <base_util/memorystream.h>
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
class PostcardBase
|
||||
{
|
||||
public:
|
||||
virtual ~PostcardBase() = 0;
|
||||
|
||||
typedef double DOUBLE;
|
||||
typedef float FLOAT;
|
||||
typedef long long INT64;
|
||||
typedef unsigned long long UINT64;
|
||||
typedef int32_t INT32;
|
||||
typedef uint32_t UINT32;
|
||||
typedef int16_t INT16;
|
||||
typedef uint16_t UINT16;
|
||||
typedef char INT8;
|
||||
typedef unsigned char UINT8;
|
||||
typedef bool BOOL;
|
||||
typedef void* PTR;
|
||||
};
|
||||
|
||||
class OutPostcard: public PostcardBase
|
||||
{
|
||||
public:
|
||||
// we only use 2 bytes to hold the name
|
||||
static const size_t MAX_ENCODE_NAME_LENGTH = 256;
|
||||
|
||||
virtual ~OutPostcard() = 0;
|
||||
static OutPostcard * createInstance();
|
||||
|
||||
virtual int init() = 0;
|
||||
virtual int finalize() = 0;
|
||||
virtual const MemoryStreamBase * getEncodedBuffer() const = 0;
|
||||
virtual OutMemoryStream * getInternalBuffer() = 0;
|
||||
|
||||
virtual int addDouble(const char * const name, const DOUBLE & value) = 0;
|
||||
virtual int addFloat(const char * const name, const FLOAT & value) = 0;
|
||||
virtual int addInt64(const char * const name, const INT64 & value) = 0;
|
||||
virtual int addUInt64(const char * const name, const UINT64 & value) = 0;
|
||||
virtual int addInt32(const char * const name, const INT32 & value) = 0;
|
||||
virtual int addUInt32(const char * const name, const UINT32 & value) = 0;
|
||||
virtual int addInt16(const char * const name, const INT16 & value) = 0;
|
||||
virtual int addUInt16(const char * const name, const UINT16 & value) = 0;
|
||||
virtual int addInt8(const char * const name, const INT8 & value) = 0;
|
||||
virtual int addUInt8(const char * const name, const UINT8 & value) = 0;
|
||||
virtual int addBool(const char * const name, const BOOL & value) = 0;
|
||||
virtual int addString(const char * const name, const char * const str) = 0;
|
||||
virtual int addPtr(const char * const name, const PTR & value) = 0;
|
||||
virtual int addBlob(const char * const name, const void * const blob, const size_t length) = 0;
|
||||
virtual int addCard(const char * const name, const OutPostcard * const pCard) = 0;
|
||||
|
||||
virtual int addArrayDouble(const char * const name, const int num_element, const DOUBLE array[]) = 0;
|
||||
virtual int addArrayFloat(const char * const name, const int num_element, const FLOAT array[]) = 0;
|
||||
virtual int addArrayInt64(const char * const name, const int num_element, const INT64 array[]) = 0;
|
||||
virtual int addArrayUInt64(const char * const name, const int num_element, const UINT64 array[]) = 0;
|
||||
virtual int addArrayInt32(const char * const name, const int num_element, const INT32 array[]) = 0;
|
||||
virtual int addArrayUInt32(const char * const name, const int num_element, const UINT32 array[]) = 0;
|
||||
virtual int addArrayInt16(const char * const name, const int num_element, const INT16 array[]) = 0;
|
||||
virtual int addArrayUInt16(const char * const name, const int num_element, const UINT16 array[]) = 0;
|
||||
virtual int addArrayInt8(const char * const name, const int num_element, const INT8 array[]) = 0;
|
||||
virtual int addArrayUInt8(const char * const name, const int num_element, const UINT8 array[]) = 0;
|
||||
virtual int addArrayBool(const char * const name, const int num_element, const BOOL array[]) = 0;
|
||||
virtual int addArrayPtr (const char * const name, const int num_element, const PTR array[]) = 0;
|
||||
};
|
||||
|
||||
class InPostcard: public PostcardBase
|
||||
{
|
||||
public:
|
||||
virtual ~InPostcard() = 0;
|
||||
static InPostcard * createInstance();
|
||||
|
||||
// assume ownership of the memory stream pointed by pInMem
|
||||
// the memory stream object will be deleted in our destructor
|
||||
// whether the actual memory block will be deleted with the destructor of
|
||||
// that InMemoryStream depends on the ownership setting of that InMemoryStream
|
||||
static InPostcard * createInstance(InMemoryStream * const pInMem);
|
||||
|
||||
// assume ownership of the memory stream pointed by pCard->getEncodedBuffer
|
||||
// the memory stream object will be deleted in our destructor
|
||||
// pCard becomes useless can can only be deleted after this operation
|
||||
static InPostcard * createInstance(OutPostcard * const pCard);
|
||||
|
||||
// doesn't assume ownership of the memory pointed by pIn
|
||||
// the memory block won't be deleted in our destructor
|
||||
virtual int init(const void * const pIn, const size_t length, bool assume_ownership = false) = 0;
|
||||
virtual const MemoryStreamBase * getBuffer() const = 0;
|
||||
|
||||
static const int FIELD_NOT_FOUND = -1;
|
||||
virtual int getDouble(const char * const name, DOUBLE & value) = 0;
|
||||
virtual int getFloat(const char * const name, FLOAT & value) = 0;
|
||||
virtual int getInt64(const char * const name, INT64 & value) = 0;
|
||||
virtual int getUInt64(const char * const name, UINT64 & value) = 0;
|
||||
virtual int getInt32(const char * const name, INT32 & value) = 0;
|
||||
virtual int getUInt32(const char * const name, UINT32 & value) = 0;
|
||||
virtual int getInt16(const char * const name, INT16 & value) = 0;
|
||||
virtual int getUInt16(const char * const name, UINT16 & value) = 0;
|
||||
virtual int getInt8(const char * const name, INT8 & value) = 0;
|
||||
virtual int getUInt8(const char * const name, UINT8 & value) = 0;
|
||||
//virtual int getArrayUInt8(const char * const name, UINT8 array[]) = 0;
|
||||
virtual int getBool(const char * const name, BOOL & value) = 0;
|
||||
virtual int getString(const char * const name, const char ** pStr) = 0;
|
||||
virtual int getStringDup(const char * const name, const char ** pStr) = 0;
|
||||
|
||||
virtual int getDoubleDefault(const char * const name, DOUBLE & value) = 0;
|
||||
virtual int getFloatDefault(const char * const name, FLOAT & value) = 0;
|
||||
virtual int getInt64Default(const char * const name, INT64 & value) = 0;
|
||||
virtual int getUInt64Default(const char * const name, UINT64 & value) = 0;
|
||||
virtual int getInt32Default(const char * const name, INT32 & value) = 0;
|
||||
virtual int getUInt32Default(const char * const name, UINT32 & value) = 0;
|
||||
virtual int getInt16Default(const char * const name, INT16 & value) = 0;
|
||||
virtual int getUInt16Default(const char * const name, UINT16 & value) = 0;
|
||||
virtual int getInt8Default(const char * const name, INT8 & value) = 0;
|
||||
virtual int getUInt8Default(const char * const name, UINT8 & value) = 0;
|
||||
virtual int getBoolDefault(const char * const name, BOOL & value) = 0;
|
||||
virtual int getStringOptional(const char * const name, const char ** pStr) = 0;
|
||||
virtual int getPtr(const char * const name, PTR & value) = 0;
|
||||
|
||||
virtual int getBlob(const char * const name, const void ** const pBlob, size_t * const pLength) = 0;
|
||||
virtual int getCard(const char * const name, InPostcard ** const ppCard, const int index = 0) = 0;
|
||||
|
||||
// Note for alignment issue, we cannot directly return a pointer pointing to internal buffer
|
||||
// so we have to explicitly allocate and de-allocate a memory block according to alignment rule
|
||||
// call these functions twice. first set array to 0 and get the number of elements
|
||||
virtual int getArrayDouble(const char * const name, int * const pNumElem, DOUBLE * const array = 0) = 0;
|
||||
virtual int getArrayFloat(const char * const name, int * const pNumElem, FLOAT * const array = 0) = 0;
|
||||
virtual int getArrayInt64(const char * const name, int * const pNumElem, INT64 * const array = 0) = 0;
|
||||
virtual int getArrayUInt64(const char * const name, int * const pNumElem, UINT64 * const array = 0) = 0;
|
||||
virtual int getArrayInt32(const char * const name, int * const pNumElem, INT32 * const array = 0) = 0;
|
||||
virtual int getArrayUInt32(const char * const name, int * const pNumElem, UINT32 * const array = 0) = 0;
|
||||
virtual int getArrayInt16(const char * const name, int * const pNumElem, INT16 * const array = 0) = 0;
|
||||
virtual int getArrayUInt16(const char * const name, int * const pNumElem, UINT16 * const array = 0) = 0;
|
||||
virtual int getArrayInt8(const char * const name, int * const pNumElem, INT8 * const array = 0) = 0;
|
||||
virtual int getArrayUInt8(const char * const name, int * const pNumElem, UINT8 * const array = 0) = 0;
|
||||
virtual int getArrayBool(const char * const name, int * const pNumElem, BOOL * const array = 0) = 0;
|
||||
virtual int getArrayPtr (const char * const name, int * const pNumElem, PTR * const array = 0) = 0;
|
||||
|
||||
};
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
#endif // #ifndef __XTRAT_WIFI_POSTCARD_H__
|
||||
143
qcom/opensource/location/utils/base_util/queue.h
Normal file
143
qcom/opensource/location/utils/base_util/queue.h
Normal file
@@ -0,0 +1,143 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Queue template
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This component implements a queue of any type
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#ifndef __XTRAT_WIFI_QUEUE_H__
|
||||
#define __XTRAT_WIFI_QUEUE_H__
|
||||
|
||||
#include <base_util/list.h>
|
||||
#include <base_util/log.h>
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class Queue: public List<T>
|
||||
{
|
||||
private:
|
||||
static const char * const TAG;
|
||||
public:
|
||||
Queue()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Queue()
|
||||
{
|
||||
}
|
||||
|
||||
int push(const T& rhs)
|
||||
{
|
||||
// our specific requirement says pushing, or enqueuing, should be as fast as possible
|
||||
// this is exactly what list does for us: always O(1) for insertion at the head
|
||||
return this->add(rhs);
|
||||
}
|
||||
|
||||
int top(T * const pValue)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(0 == pValue)
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
SingleListNode<T> * pLastNode = 0;
|
||||
//SingleListNode<T> * pSecondLastNode = 0;
|
||||
SingleListNode<T> * pNode = List<T>::m_pHead;
|
||||
while (0 != pNode)
|
||||
{
|
||||
//pSecondLastNode = pLastNode;
|
||||
pLastNode = pNode;
|
||||
pNode = pNode->getNext();
|
||||
}
|
||||
|
||||
if(0 != pLastNode)
|
||||
{
|
||||
*pValue = pLastNode->getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
// we started with an empty queue
|
||||
result = 3;
|
||||
break;
|
||||
}
|
||||
result = 0;
|
||||
} while (false);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "top: failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int pop(T * const pValue)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(0 == pValue)
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
SingleListNode<T> * pLastNode = 0;
|
||||
SingleListNode<T> * pSecondLastNode = 0;
|
||||
SingleListNode<T> * pNode = List<T>::m_pHead;
|
||||
while (0 != pNode)
|
||||
{
|
||||
pSecondLastNode = pLastNode;
|
||||
pLastNode = pNode;
|
||||
pNode = pNode->getNext();
|
||||
}
|
||||
|
||||
if(0 != pSecondLastNode)
|
||||
{
|
||||
pSecondLastNode->setNext(0);
|
||||
List<T>::m_size = List<T>::m_size - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// nothing, we only had 1 element and we just removed it
|
||||
List<T>::m_pHead = 0;
|
||||
List<T>::m_size = 0;
|
||||
}
|
||||
|
||||
if(0 != pLastNode)
|
||||
{
|
||||
*pValue = pLastNode->getValue();
|
||||
delete pLastNode;
|
||||
pLastNode = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we started with an empty queue
|
||||
result = 3;
|
||||
break;
|
||||
}
|
||||
result = 0;
|
||||
} while (false);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "pop: failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
const char * const Queue<T>::TAG = "Queue";
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
#endif //#ifndef __XTRAT_WIFI_QUEUE_H__
|
||||
67
qcom/opensource/location/utils/base_util/shutdown_timer.h
Normal file
67
qcom/opensource/location/utils/base_util/shutdown_timer.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#ifndef SHUTDOWN_TIMER_H
|
||||
#define SHUTDOWN_TIMER_H
|
||||
|
||||
#include "LocTimer.h"
|
||||
#include "loc_cfg.h"
|
||||
#include "log_util.h"
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#define PROCESS_SHUTDOWN_TIMEOUT_IN_MS 300000
|
||||
|
||||
namespace qc_loc_fw {
|
||||
class ProcessShutdownTimer : public loc_util::LocTimer {
|
||||
public:
|
||||
~ProcessShutdownTimer() = default;
|
||||
ProcessShutdownTimer(std::string name, const std::function<void()> shutdownCb) :
|
||||
loc_util::LocTimer(), mShutdownCb(shutdownCb), mActive(false),
|
||||
mShutdownTimerInMs(PROCESS_SHUTDOWN_TIMEOUT_IN_MS), mLaunchTriggerMask(0),
|
||||
mProcessName(name) {
|
||||
const loc_param_s_type gpsConfTable[] = {
|
||||
{"PROCESS_SHUTDOWN_TIMER_IN_MS", &mShutdownTimerInMs, NULL, 'n'}};
|
||||
UTIL_READ_CONF(LOC_PATH_GPS_CONF, gpsConfTable);
|
||||
}
|
||||
inline void start() {
|
||||
if (mLaunchTriggerMask > 0) {
|
||||
LOC_LOGd("Started shutdown timer for process %s", mProcessName.c_str());
|
||||
mActive = true;
|
||||
loc_util::LocTimer::start(mShutdownTimerInMs, false);
|
||||
}
|
||||
}
|
||||
|
||||
inline void stop() {
|
||||
if (mLaunchTriggerMask > 0) {
|
||||
LOC_LOGd("Stopped shutdown timer for process %s", mProcessName.c_str());
|
||||
mActive = false;
|
||||
loc_util::LocTimer::stop();
|
||||
}
|
||||
}
|
||||
|
||||
inline void restart() {
|
||||
if (mLaunchTriggerMask > 0) {
|
||||
LOC_LOGd("Restarted shutdown timer for process %s", mProcessName.c_str());
|
||||
stop();
|
||||
start();
|
||||
}
|
||||
}
|
||||
inline bool isActive() {
|
||||
return mActive;
|
||||
}
|
||||
inline void setLaunchTriggerMask(int16_t launchTriggerMask) {
|
||||
mLaunchTriggerMask = launchTriggerMask;
|
||||
}
|
||||
private:
|
||||
inline virtual void timeOutCallback() override {
|
||||
mShutdownCb();
|
||||
}
|
||||
const std::function<void()> mShutdownCb;
|
||||
bool mActive;
|
||||
std::string mProcessName;
|
||||
uint32_t mShutdownTimerInMs;
|
||||
uint16_t mLaunchTriggerMask;
|
||||
};
|
||||
} // namespace qc_loc_fw
|
||||
#endif /* SHUTDOWN_TIMER_H */
|
||||
51
qcom/opensource/location/utils/base_util/src/Makefile.am
Normal file
51
qcom/opensource/location/utils/base_util/src/Makefile.am
Normal file
@@ -0,0 +1,51 @@
|
||||
AM_CFLAGS = \
|
||||
-I../ \
|
||||
-I../../base_util \
|
||||
-I../../ \
|
||||
-D__func__=__PRETTY_FUNCTION__ \
|
||||
-fno-short-enums
|
||||
|
||||
h_sources = \
|
||||
../config_file.h \
|
||||
../log.h \
|
||||
../postcard.h \
|
||||
../sync.h \
|
||||
../queue.h \
|
||||
../list.h \
|
||||
../memorystream.h \
|
||||
../nvparam_mgr.h \
|
||||
../time_routines.h \
|
||||
../vector.h \
|
||||
../array.h \
|
||||
../string_routines.h \
|
||||
../shutdown_timer.h
|
||||
|
||||
libloc_base_util_la_SOURCES = \
|
||||
config_file.cpp \
|
||||
log.cpp \
|
||||
memorystream.cpp \
|
||||
nvparam_mgr.cpp \
|
||||
postcard.cpp \
|
||||
sync.cpp \
|
||||
string_routines.cpp \
|
||||
time_routines.cpp
|
||||
library_includedir = $(pkgincludedir)
|
||||
library_include_HEADERS = $(h_sources)
|
||||
|
||||
if USE_GLIB
|
||||
libloc_base_util_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@ -Dstrlcat=g_strlcat -Dstrlcpy=g_strlcpy -include glib.h
|
||||
libloc_base_util_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0
|
||||
libloc_base_util_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@ -Dstrlcat=g_strlcat -Dstrlcpy=g_strlcpy -include glib.h
|
||||
else
|
||||
libloc_base_util_la_CFLAGS = $(AM_CFLAGS)
|
||||
libloc_base_util_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0
|
||||
libloc_base_util_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
|
||||
endif
|
||||
|
||||
libloc_base_util_la_LIBADD = -lstdc++ -ldl -lsqlite3
|
||||
|
||||
#Create and Install libraries
|
||||
lib_LTLIBRARIES = libloc_base_util.la
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = ../loc-base-util.pc
|
||||
EXTRA_DIST = $(pkgconfig_DATA)
|
||||
734
qcom/opensource/location/utils/base_util/src/config_file.cpp
Normal file
734
qcom/opensource/location/utils/base_util/src/config_file.cpp
Normal file
@@ -0,0 +1,734 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Config file parser
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This component parses any specified config file and allows to be queried later
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#include <new>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <base_util/log.h>
|
||||
#include <base_util/list.h>
|
||||
#include <base_util/config_file.h>
|
||||
|
||||
#define BREAK_IF_ZERO(ERR,X) if(0==(X)) {result = (ERR); break;}
|
||||
#define BREAK_IF_NON_ZERO(ERR,X) if(0!=(X)) {result = (ERR); break;}
|
||||
#define BREAK_IF_NON_ZERO_RC(ERR,RC,X) if(0!=(RC=(X))) {result = (ERR); break;}
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
static const char * const TAG = "ConfigFile";
|
||||
|
||||
ConfigFile::~ConfigFile()
|
||||
{
|
||||
// dummy
|
||||
}
|
||||
|
||||
struct ConfigPair
|
||||
{
|
||||
const char * name;
|
||||
const char * value;
|
||||
};
|
||||
|
||||
class ConfigFileImpl: public ConfigFile
|
||||
{
|
||||
public:
|
||||
ConfigFileImpl(const char * const filename, const size_t max_line_length, const bool verbose);
|
||||
~ConfigFileImpl();
|
||||
|
||||
bool loaded() const
|
||||
{
|
||||
return m_loaded;
|
||||
}
|
||||
;
|
||||
|
||||
int getString(const char * const name, const char ** pStr);
|
||||
int getStringDup(const char * const name, const char ** pStr, const char * const strDefault);
|
||||
int getInt32(const char * const name, int & value);
|
||||
int getInt32Default(const char * const name, int & value, const int & Default);
|
||||
int get_PZ_Int32Default(const char * const name, int & value, const int & Default);
|
||||
int get_PNZ_Int32Default(const char * const name, int & value, const int & Default);
|
||||
int getDouble(const char * const name, double & value);
|
||||
int getDoubleDefault(const char * const name, double & value, const double & Default);
|
||||
private:
|
||||
bool m_loaded;
|
||||
|
||||
typedef List<ConfigPair> PAIRS;
|
||||
PAIRS m_config;
|
||||
|
||||
void trim(size_t & cursor_begin, size_t & cursor_end, const char * const line);
|
||||
void substring(char * dest, const size_t capacity, const char * const src, const size_t begin, const size_t end);
|
||||
int find_name(size_t & cursor_begin, size_t & cursor_end, const char * const line, size_t & name_begin,
|
||||
size_t & name_end);
|
||||
int find_equal(size_t & cursor_begin, size_t & cursor_end, const char * const line);
|
||||
int find_value(size_t & cursor_begin, size_t & cursor_end, const char * const line, size_t & value_begin,
|
||||
size_t & value_end);
|
||||
|
||||
const char * subStringDup(const char * const src, const size_t begin, const size_t end);
|
||||
};
|
||||
|
||||
void ConfigFileImpl::trim(size_t & cursor_begin, size_t & cursor_end, const char * const line)
|
||||
{
|
||||
// check arguments
|
||||
if(cursor_end <= cursor_begin)
|
||||
{
|
||||
// empty line already
|
||||
return;
|
||||
}
|
||||
|
||||
// left trim
|
||||
for (; cursor_begin < cursor_end; ++cursor_begin)
|
||||
{
|
||||
if(!isspace(line[cursor_begin]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// right trim
|
||||
for (; cursor_begin < cursor_end; --cursor_end)
|
||||
{
|
||||
if(!isspace(line[cursor_end - 1]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigFileImpl::substring(char * dest, const size_t capacity, const char * const src, const size_t begin,
|
||||
const size_t end)
|
||||
{
|
||||
memset(dest, 0, capacity);
|
||||
for (size_t i = begin, d = 0; ((i < end) && (d < capacity)); ++i, ++d)
|
||||
{
|
||||
dest[d] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
const char * ConfigFileImpl::subStringDup(const char * const src, const size_t begin, const size_t end)
|
||||
{
|
||||
char * dest = 0;
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(begin >= end)
|
||||
{
|
||||
result = 2;
|
||||
}
|
||||
BREAK_IF_ZERO(3, src);
|
||||
|
||||
size_t length = end - begin;
|
||||
|
||||
dest = new (std::nothrow) char[length + 1];
|
||||
BREAK_IF_ZERO(4, dest);
|
||||
memcpy(dest, src + begin, length);
|
||||
dest[length] = '\0';
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
delete[] dest;
|
||||
log_error(TAG, "subStringDup failed %d", result);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
|
||||
int ConfigFileImpl::find_name(size_t & cursor_begin, size_t & cursor_end, const char * const line, size_t & name_begin,
|
||||
size_t & name_end)
|
||||
{
|
||||
if(0 == line)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if(cursor_begin >= cursor_end)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (size_t i = cursor_begin; i < cursor_end; ++i)
|
||||
{
|
||||
if(!found)
|
||||
{
|
||||
if(isalpha(line[i]))
|
||||
{
|
||||
found = true;
|
||||
name_begin = i;
|
||||
name_end = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isalnum(line[i]) || ('-' == line[i]) || ('_' == line[i]))
|
||||
{
|
||||
name_end = i + 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(found)
|
||||
{
|
||||
cursor_begin = name_end;
|
||||
trim(cursor_begin, cursor_end, line);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
int ConfigFileImpl::find_equal(size_t & cursor_begin, size_t & cursor_end, const char * const line)
|
||||
{
|
||||
|
||||
if(0 == line)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if(cursor_begin >= cursor_end)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
if('=' == line[cursor_begin])
|
||||
{
|
||||
++cursor_begin;
|
||||
trim(cursor_begin, cursor_end, line);
|
||||
return 0;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
int ConfigFileImpl::find_value(size_t & cursor_begin, size_t & cursor_end, const char * const line,
|
||||
size_t & value_begin, size_t & value_end)
|
||||
{
|
||||
if(0 == line)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if(cursor_begin >= cursor_end)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
value_begin = cursor_begin;
|
||||
value_end = cursor_end;
|
||||
|
||||
cursor_begin = cursor_end;
|
||||
|
||||
if('"' == line[value_begin])
|
||||
{
|
||||
if(value_end - value_begin >= 2)
|
||||
{
|
||||
if('"' == line[value_end - 1])
|
||||
{
|
||||
// remove double quote
|
||||
++value_begin;
|
||||
--value_end;
|
||||
}
|
||||
else
|
||||
{
|
||||
// start with " but doesn't end with one
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// start with " but doesn't end with one
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ConfigFileImpl::ConfigFileImpl(const char * const filename, const size_t max_line_length, const bool verbose) :
|
||||
m_loaded(false)
|
||||
{
|
||||
ConfigPair pair;
|
||||
pair.name = 0;
|
||||
pair.value = 0;
|
||||
|
||||
char * line_debug = 0;
|
||||
char * line = 0;
|
||||
FILE * file = 0;
|
||||
int result = 1;
|
||||
int line_index = 0;
|
||||
do
|
||||
{
|
||||
BREAK_IF_ZERO(2, filename);
|
||||
file = fopen(filename, "r");
|
||||
BREAK_IF_ZERO(3, file);
|
||||
|
||||
line = new (std::nothrow) char[max_line_length + 1];
|
||||
BREAK_IF_ZERO(4, line);
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
line_debug = new (std::nothrow) char[max_line_length + 1];
|
||||
BREAK_IF_ZERO(5, line_debug);
|
||||
line_debug[0] = '\0';
|
||||
}
|
||||
|
||||
line[0] = '\0';
|
||||
result = 100;
|
||||
while (0 != fgets(line, max_line_length + 1, file))
|
||||
{
|
||||
++line_index;
|
||||
//log_verbose(TAG, "line [%s]", line);
|
||||
|
||||
size_t length = strlen(line);
|
||||
if(length >= max_line_length)
|
||||
{
|
||||
// line too long
|
||||
result = 101;
|
||||
break;
|
||||
}
|
||||
|
||||
// token type 1: # comment till the end of line
|
||||
// token type 2: name, can only contain alphanumeric,'_', and '-'
|
||||
// token type 3: '='
|
||||
// token type 4: value: anything starting from the first non-space char after '=' to the end of this (trimmed) line
|
||||
|
||||
size_t cursor_begin = 0;
|
||||
size_t cursor_end = length;
|
||||
trim(cursor_begin, cursor_end, line);
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
substring(line_debug, max_line_length + 1, line, cursor_begin, cursor_end);
|
||||
log_debug(TAG, "line trimed [%s]", line_debug);
|
||||
}
|
||||
|
||||
if(cursor_begin >= cursor_end)
|
||||
{
|
||||
// empty line already
|
||||
if(verbose)
|
||||
{
|
||||
log_verbose(TAG, "Line[%d], skip empty line", line_index);
|
||||
}
|
||||
}
|
||||
else if('#' == line[cursor_begin])
|
||||
{
|
||||
// this whole line is comment
|
||||
cursor_begin = cursor_end;
|
||||
if(verbose)
|
||||
{
|
||||
log_verbose(TAG, "Line[%d], skip comment line", line_index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we shall see name = value pattern
|
||||
size_t name_begin = cursor_end;
|
||||
size_t name_end = cursor_end;
|
||||
size_t value_begin = cursor_end;
|
||||
size_t value_end = cursor_end;
|
||||
BREAK_IF_NON_ZERO(110, find_name(cursor_begin, cursor_end, line, name_begin, name_end));
|
||||
BREAK_IF_NON_ZERO(111, find_equal(cursor_begin, cursor_end, line));
|
||||
BREAK_IF_NON_ZERO(112, find_value(cursor_begin, cursor_end, line, value_begin, value_end));
|
||||
if(cursor_begin < cursor_end)
|
||||
{
|
||||
// still anything after 'value' token!?
|
||||
// error
|
||||
result = 113;
|
||||
break;
|
||||
}
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
substring(line_debug, max_line_length + 1, line, name_begin, name_end);
|
||||
log_verbose(TAG, "name [%s]", line_debug);
|
||||
|
||||
substring(line_debug, max_line_length + 1, line, value_begin, value_end);
|
||||
log_verbose(TAG, "value [%s]", line_debug);
|
||||
}
|
||||
|
||||
pair.name = subStringDup(line, name_begin, name_end);
|
||||
pair.value = subStringDup(line, value_begin, value_end);
|
||||
|
||||
BREAK_IF_ZERO(114, pair.name);
|
||||
BREAK_IF_ZERO(115, pair.value);
|
||||
BREAK_IF_NON_ZERO(116, m_config.add(pair));
|
||||
|
||||
// we don't own them now
|
||||
pair.name = 0;
|
||||
pair.value = 0;
|
||||
}
|
||||
|
||||
// reset the string
|
||||
line[0] = '\0';
|
||||
|
||||
if(line_debug)
|
||||
{
|
||||
line_debug[0] = '\0';
|
||||
}
|
||||
}
|
||||
if(100 != result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
BREAK_IF_NON_ZERO(10, ferror(file));
|
||||
|
||||
m_loaded = true;
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
delete[] line;
|
||||
line = 0;
|
||||
|
||||
delete[] pair.name;
|
||||
pair.name = 0;
|
||||
delete[] pair.value;
|
||||
pair.value = 0;
|
||||
|
||||
delete[] line_debug;
|
||||
line_debug = 0;
|
||||
|
||||
if(0 != file)
|
||||
{
|
||||
(void) fclose(file);
|
||||
file = 0;
|
||||
}
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "ConfigFileImpl: cannot load config file result [%d] [%s], error [%d][%s], line[%d]", result,
|
||||
filename, errno, strerror(errno), line_index);
|
||||
}
|
||||
}
|
||||
|
||||
ConfigFileImpl::~ConfigFileImpl()
|
||||
{
|
||||
for (PAIRS::Iterator it = m_config.begin(); it != m_config.end(); ++it)
|
||||
{
|
||||
ConfigPair & pair = (*it);
|
||||
delete[] pair.name;
|
||||
delete[] pair.value;
|
||||
|
||||
pair.name = 0;
|
||||
pair.value = 0;
|
||||
}
|
||||
m_config.flush();
|
||||
}
|
||||
|
||||
int ConfigFileImpl::getString(const char * const name, const char ** pStr)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_loaded)
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
BREAK_IF_ZERO(3, name);
|
||||
BREAK_IF_ZERO(4, pStr);
|
||||
*pStr = 0;
|
||||
|
||||
result = NOT_FOUND;
|
||||
for (PAIRS::Iterator it = m_config.begin(); it != m_config.end(); ++it)
|
||||
{
|
||||
ConfigPair & pair = (*it);
|
||||
if(0 == strcmp(name, pair.name))
|
||||
{
|
||||
*pStr = pair.value;
|
||||
result = NO_ERROR_RESULT_SET;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if((NO_ERROR_RESULT_SET != result) && (NOT_FOUND != result))
|
||||
{
|
||||
if(name)
|
||||
{
|
||||
log_error(TAG, "getString failed [%s] %d", name, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "getString failed %d", result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ConfigFileImpl::getStringDup(const char * const name, const char ** pStr, const char * const strDefault)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_loaded)
|
||||
{
|
||||
// if not loaded, set return to NOT_FOUND, so that default value (strDefault) can be returned.
|
||||
result = NOT_FOUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
BREAK_IF_ZERO(3, name);
|
||||
BREAK_IF_ZERO(4, pStr);
|
||||
*pStr = 0;
|
||||
|
||||
result = NOT_FOUND;
|
||||
for (PAIRS::Iterator it = m_config.begin(); it != m_config.end(); ++it)
|
||||
{
|
||||
ConfigPair & pair = (*it);
|
||||
if(0 == strcmp(name, pair.name))
|
||||
{
|
||||
size_t length = strlen(pair.value) + 1;
|
||||
*pStr = new (std::nothrow) char[length];
|
||||
BREAK_IF_ZERO(101, *pStr);
|
||||
memcpy((void *) *pStr, (const void *) pair.value, length);
|
||||
result = NO_ERROR_RESULT_SET;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((NOT_FOUND == result) && (0 != strDefault))
|
||||
{
|
||||
size_t length = strlen(strDefault) + 1;
|
||||
*pStr = new (std::nothrow) char[length];
|
||||
BREAK_IF_ZERO(111, *pStr);
|
||||
memcpy((void *) *pStr, (const void *) strDefault, length);
|
||||
result = NO_ERROR_RESULT_SET;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if((NO_ERROR_RESULT_SET != result) && (NOT_FOUND != result))
|
||||
{
|
||||
if(name)
|
||||
{
|
||||
log_error(TAG, "getStringDup failed [%s] %d", name, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "getStringDup failed %d", result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ConfigFileImpl::get_PZ_Int32Default(const char * const name, int & value, const int & Default)
|
||||
{
|
||||
int result = getInt32(name, value);
|
||||
if(NOT_FOUND == result)
|
||||
{
|
||||
value = Default;
|
||||
return 0;
|
||||
}
|
||||
else if(value < 0)
|
||||
{
|
||||
value = Default;
|
||||
return 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ConfigFileImpl::get_PNZ_Int32Default(const char * const name, int & value, const int & Default)
|
||||
{
|
||||
int result = getInt32(name, value);
|
||||
if(NOT_FOUND == result)
|
||||
{
|
||||
value = Default;
|
||||
return 0;
|
||||
}
|
||||
else if(value <= 0)
|
||||
{
|
||||
value = Default;
|
||||
return 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ConfigFileImpl::getInt32Default(const char * const name, int & value, const int & Default)
|
||||
{
|
||||
int result = getInt32(name, value);
|
||||
if(NOT_FOUND == result)
|
||||
{
|
||||
value = Default;
|
||||
return 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ConfigFileImpl::getInt32(const char * const name, int & value)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_loaded)
|
||||
{
|
||||
// if not loaded, return NOT_FOUND, so that other util functions invoking
|
||||
// this function (eg:getInt32Default) can return back default value.
|
||||
log_debug(TAG, "getInt32 m_loaded is false");
|
||||
result = NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
BREAK_IF_ZERO(3, name);
|
||||
|
||||
result = NOT_FOUND;
|
||||
for (PAIRS::Iterator it = m_config.begin(); it != m_config.end(); ++it)
|
||||
{
|
||||
ConfigPair & pair = (*it);
|
||||
if(0 == strcmp(name, pair.name))
|
||||
{
|
||||
if(strlen(pair.value) < 1)
|
||||
{
|
||||
result = 101;
|
||||
break;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
char * end_ptr = 0;
|
||||
long temp = strtol(pair.value, &end_ptr, 0);
|
||||
if((LONG_MAX == temp) || (LONG_MIN == temp))
|
||||
{
|
||||
result = 102;
|
||||
}
|
||||
else if(0 != errno)
|
||||
{
|
||||
// conversion error
|
||||
log_error(TAG, "conversion error [%d] [%s]", errno, strerror(errno));
|
||||
result = 103;
|
||||
}
|
||||
else if('\0' != *end_ptr)
|
||||
{
|
||||
// string not fully consumed
|
||||
result = 104;
|
||||
}
|
||||
else if((temp > INT_MAX) || (temp < INT_MIN))
|
||||
{
|
||||
// beyond range for int32
|
||||
result = 105;
|
||||
}
|
||||
else
|
||||
{
|
||||
// conversion okay
|
||||
value = (int) temp;
|
||||
result = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if((NO_ERROR_RESULT_SET != result) && (NOT_FOUND != result))
|
||||
{
|
||||
if(name)
|
||||
{
|
||||
log_error(TAG, "getInt32 failed [%s] %d", name, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "getInt32 failed %d", result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ConfigFileImpl::getDoubleDefault(const char * const name, double & value, const double & Default)
|
||||
{
|
||||
int result = getDouble(name, value);
|
||||
if(NOT_FOUND == result)
|
||||
{
|
||||
value = Default;
|
||||
return 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ConfigFileImpl::getDouble(const char * const name, double & value)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_loaded)
|
||||
{
|
||||
// if not loaded, return NOT_FOUND, so that other util functions invoking
|
||||
// this function (eg:getDoubleDefault) can return back default value.
|
||||
log_debug(TAG, "getDouble m_loaded is false");
|
||||
result = NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
BREAK_IF_ZERO(3, name);
|
||||
|
||||
result = NOT_FOUND;
|
||||
for (PAIRS::Iterator it = m_config.begin(); it != m_config.end(); ++it)
|
||||
{
|
||||
ConfigPair & pair = (*it);
|
||||
if(0 == strcmp(name, pair.name))
|
||||
{
|
||||
if(strlen(pair.value) < 1)
|
||||
{
|
||||
result = 101;
|
||||
break;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
char * end_ptr = 0;
|
||||
double temp = strtod(pair.value, &end_ptr);
|
||||
if(0 != errno)
|
||||
{
|
||||
// conversion error
|
||||
log_error(TAG, "conversion error [%d] [%s]", errno, strerror(errno));
|
||||
result = 102;
|
||||
}
|
||||
else if('\0' != *end_ptr)
|
||||
{
|
||||
// string not fully consumed
|
||||
result = 103;
|
||||
}
|
||||
else
|
||||
{
|
||||
// conversion okay
|
||||
value = temp;
|
||||
result = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if((NO_ERROR_RESULT_SET != result) && (NOT_FOUND != result))
|
||||
{
|
||||
if(name)
|
||||
{
|
||||
log_error(TAG, "getDouble failed [%s] %d", name, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "getDouble failed %d", result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ConfigFile * ConfigFile::createInstance(const char * const filename, const size_t max_line_length, const bool verbose)
|
||||
{
|
||||
return new (std::nothrow) ConfigFileImpl(filename, max_line_length, verbose);
|
||||
}
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
524
qcom/opensource/location/utils/base_util/src/log.cpp
Normal file
524
qcom/opensource/location/utils/base_util/src/log.cpp
Normal file
@@ -0,0 +1,524 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Log utility
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This component provides logging service to all client side components
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <new>
|
||||
|
||||
//#include <base_util/log.h>
|
||||
#include <base_util/sync.h>
|
||||
#include <base_util/list.h>
|
||||
#include <base_util/string_routines.h>
|
||||
#include <base_util/time_routines.h>
|
||||
|
||||
#define DEFAULT_ERROR_OUTPUT EO_STDOUT
|
||||
|
||||
#if defined (USE_ANDROID_LOGGING) || defined (__ANDROID__)
|
||||
// Android and LE targets with logcat support
|
||||
#define LOG_NDEBUG 0
|
||||
|
||||
// these 2 symbols are needed on ICS for DEBUG- and INFO-level
|
||||
// log messages to be processed. They are not neeeded on JB
|
||||
#define LOG_NDEBUG 0
|
||||
#define LOG_NIDEBUG 0
|
||||
|
||||
#define LOG_TAG NULL
|
||||
|
||||
#ifdef __ANDROID_NDK__
|
||||
#include <android/log.h>
|
||||
|
||||
#define ANDROID_LOG __android_log_print
|
||||
#define LOG_VERBOSE ANDROID_LOG_VERBOSE
|
||||
#define LOG_DEBUG ANDROID_LOG_DEBUG
|
||||
#define LOG_INFO ANDROID_LOG_INFO
|
||||
#define LOG_WARN ANDROID_LOG_WARN
|
||||
#define LOG_ERROR ANDROID_LOG_ERROR
|
||||
#else // #ifdef __ANDROID_NDK__
|
||||
#include <utils/Log.h>
|
||||
#ifdef ALOG
|
||||
#define ANDROID_LOG ALOG
|
||||
#else // #ifdef ALOG
|
||||
#define ANDROID_LOG LOG
|
||||
#endif // #ifdef ALOG
|
||||
#endif // #ifdef __ANDROID_NDK__
|
||||
#undef DEFAULT_ERROR_OUTPUT
|
||||
#define DEFAULT_ERROR_OUTPUT EO_ANDROID
|
||||
#endif // #if defined (USE_ANDROID_LOGGING) || defined (__ANDROID__)
|
||||
|
||||
#define BREAK_IF_ZERO(ERR,X) if(0==(X)) {result = (ERR); break;}
|
||||
#define BREAK_IF_NON_ZERO(ERR,X) if(0!=(X)) {result = (ERR); break;}
|
||||
#define BREAK_IF_NON_ZERO_RC(ERR,RC,X) if(0!=(RC=(X))) {result = (ERR); break;}
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
class LocalLogLevelItem;
|
||||
static char global_log_tag[64] = { 'Q', 'C', 'A', 'L', 'O', 'G', '\0' };
|
||||
static ERROR_LEVEL global_log_level = EL_LOG_OFF;
|
||||
static const char * const private_log_tag = "LOG_UTIL";
|
||||
static Mutex * global_log_mutex = Mutex::createInstance();
|
||||
static List<LocalLogLevelItem> * local_log_level_list =
|
||||
new (std::nothrow) List<LocalLogLevelItem>();
|
||||
|
||||
class LocalLogLevelItem
|
||||
{
|
||||
private:
|
||||
char * local_tag;
|
||||
ERROR_LEVEL local_log_level;
|
||||
ERROR_OUTPUT local_output;
|
||||
|
||||
void setTag(const char * const tag)
|
||||
{
|
||||
if(0 != tag)
|
||||
{
|
||||
local_tag = strdup(tag);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
const char * getTag() const
|
||||
{
|
||||
return local_tag;
|
||||
}
|
||||
|
||||
void setLevel(const ERROR_LEVEL level)
|
||||
{
|
||||
local_log_level = level;
|
||||
}
|
||||
|
||||
void setOutput(const ERROR_OUTPUT output)
|
||||
{
|
||||
local_output = output;
|
||||
}
|
||||
|
||||
ERROR_LEVEL getLevel() const
|
||||
{
|
||||
return local_log_level;
|
||||
}
|
||||
|
||||
ERROR_OUTPUT getOutput() const
|
||||
{
|
||||
return local_output;
|
||||
}
|
||||
|
||||
LocalLogLevelItem(const char * const tag)
|
||||
{
|
||||
setTag(tag);
|
||||
local_log_level = EL_LOG_ALL;
|
||||
local_output = DEFAULT_ERROR_OUTPUT;
|
||||
}
|
||||
|
||||
LocalLogLevelItem(const LocalLogLevelItem & rhs)
|
||||
{
|
||||
if(&rhs == this)
|
||||
{
|
||||
// no operation for assigning to self
|
||||
return;
|
||||
}
|
||||
|
||||
setTag(rhs.local_tag);
|
||||
local_log_level = rhs.local_log_level;
|
||||
local_output = rhs.local_output;
|
||||
}
|
||||
|
||||
~LocalLogLevelItem()
|
||||
{
|
||||
if(0 != local_tag)
|
||||
{
|
||||
// we got this from strdup, which uses malloc.
|
||||
free(local_tag);
|
||||
local_tag = 0;
|
||||
}
|
||||
local_tag = 0;
|
||||
}
|
||||
|
||||
bool equals(const char * const tag)
|
||||
{
|
||||
if((0 == tag) || (0 == local_tag))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(0 == strcmp(tag, local_tag))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static LocalLogLevelItem * findLocalLevelItemLocked(const char * const tag)
|
||||
{
|
||||
LocalLogLevelItem * p_item = 0;
|
||||
|
||||
if(0 != local_log_level_list)
|
||||
{
|
||||
for (ListIterator<LocalLogLevelItem> it = local_log_level_list->begin(); it != local_log_level_list->end(); ++it)
|
||||
{
|
||||
if(it->equals(tag))
|
||||
{
|
||||
p_item = it.ptr();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return p_item;
|
||||
}
|
||||
|
||||
static bool is_log_enabled(const char * const local_log_tag, const ERROR_LEVEL log_level)
|
||||
{
|
||||
bool ok_to_log = false;
|
||||
|
||||
const LocalLogLevelItem * const pLogLevelRec = findLocalLevelItemLocked(local_log_tag);
|
||||
if(0 != pLogLevelRec)
|
||||
{
|
||||
if(log_level <= pLogLevelRec->getLevel())
|
||||
{
|
||||
ok_to_log = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(log_level <= global_log_level)
|
||||
{
|
||||
ok_to_log = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ok_to_log;
|
||||
}
|
||||
|
||||
bool is_log_verbose_enabled(const char * const local_log_tag)
|
||||
{
|
||||
return is_log_enabled(local_log_tag, EL_VERBOSE);
|
||||
}
|
||||
|
||||
static void vlog(const char * const local_log_tag, const ERROR_LEVEL log_level, const char * const format, va_list args)
|
||||
{
|
||||
bool ok_to_log = false;
|
||||
const LocalLogLevelItem * const pLogLevelRec = findLocalLevelItemLocked(local_log_tag);
|
||||
ERROR_OUTPUT local_output = DEFAULT_ERROR_OUTPUT;
|
||||
if(0 != pLogLevelRec)
|
||||
{
|
||||
if(log_level <= pLogLevelRec->getLevel())
|
||||
{
|
||||
ok_to_log = true;
|
||||
}
|
||||
local_output = pLogLevelRec->getOutput();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(log_level <= global_log_level)
|
||||
{
|
||||
ok_to_log = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(ok_to_log)
|
||||
{
|
||||
int format_result = -1;
|
||||
char buffer1[512];
|
||||
char buffer2[512];
|
||||
format_result = vsnprintf(buffer1, sizeof(buffer1), format, args);
|
||||
if (0 >= format_result)
|
||||
{
|
||||
strlcpy(buffer1, "log subsystem message format error", sizeof(buffer1));
|
||||
}
|
||||
|
||||
#if defined (USE_ANDROID_LOGGING) || defined (__ANDROID__)
|
||||
if (EO_ANDROID & local_output)
|
||||
{
|
||||
if (0 != local_log_tag)
|
||||
{
|
||||
format_result = snprintf(buffer2, sizeof(buffer2), "[%s] %s", local_log_tag, buffer1);
|
||||
}
|
||||
else
|
||||
{
|
||||
format_result = snprintf(buffer2, sizeof(buffer2), "%s", buffer1);
|
||||
}
|
||||
|
||||
if (format_result > 0)
|
||||
{
|
||||
switch (log_level)
|
||||
{
|
||||
case EL_ERROR:
|
||||
ANDROID_LOG(LOG_ERROR, global_log_tag, "%s", buffer2);
|
||||
break;
|
||||
case EL_WARNING:
|
||||
ANDROID_LOG(LOG_WARN, global_log_tag, "%s", buffer2);
|
||||
break;
|
||||
case EL_INFO:
|
||||
ANDROID_LOG(LOG_INFO, global_log_tag, "%s", buffer2);
|
||||
break;
|
||||
case EL_DEBUG:
|
||||
ANDROID_LOG(LOG_DEBUG, global_log_tag, "%s", buffer2);
|
||||
break;
|
||||
case EL_VERBOSE:
|
||||
ANDROID_LOG(LOG_VERBOSE, global_log_tag, "%s", buffer2);
|
||||
break;
|
||||
default:
|
||||
ANDROID_LOG(LOG_ERROR, global_log_tag, "Internal error in log subsystem: unknown log level");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ANDROID_LOG(LOG_ERROR, global_log_tag, "Internal error in log subsystem: format error");
|
||||
}
|
||||
}
|
||||
#endif // #if defined (USE_ANDROID_LOGGING) || defined (__ANDROID__)
|
||||
|
||||
if (EO_STDOUT & local_output)
|
||||
{
|
||||
char time_string[40];
|
||||
time_t now = time(NULL);
|
||||
struct tm *curr_time = localtime(&now);
|
||||
struct tm zero_time;
|
||||
memset(&zero_time, 0, sizeof(zero_time));
|
||||
|
||||
if (nullptr == curr_time) {
|
||||
curr_time = &zero_time;
|
||||
}
|
||||
|
||||
// time format example: 11-11 11:06:02.725
|
||||
strftime(time_string, sizeof(time_string)-1, "%m-%d %H:%M:%S.000", curr_time);
|
||||
|
||||
if (0 != local_log_tag)
|
||||
{
|
||||
format_result = snprintf(buffer2, sizeof(buffer2), "%s %s:[%s] %s",
|
||||
time_string, global_log_tag, local_log_tag, buffer1);
|
||||
}
|
||||
else
|
||||
{
|
||||
format_result = snprintf(buffer2, sizeof(buffer2), "%s %s: %s",
|
||||
time_string, global_log_tag, buffer1);
|
||||
}
|
||||
|
||||
if (format_result > 0)
|
||||
{
|
||||
puts(buffer2);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("Internal error in log subsystem: format error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int log_set_global_level(const ERROR_LEVEL level)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
BREAK_IF_ZERO(2, global_log_mutex);
|
||||
|
||||
AutoLock latch(global_log_mutex);
|
||||
|
||||
BREAK_IF_NON_ZERO(3, latch.ZeroIfLocked());
|
||||
|
||||
global_log_level = level;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(private_log_tag, "log_set_global_level failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int log_set_global_tag(const char * const tag)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
BREAK_IF_ZERO(2, global_log_mutex);
|
||||
|
||||
AutoLock latch(global_log_mutex);
|
||||
|
||||
BREAK_IF_NON_ZERO(3, latch.ZeroIfLocked());
|
||||
|
||||
size_t copy_length = strlcpy(global_log_tag, tag, sizeof(global_log_tag));
|
||||
if(copy_length >= sizeof(global_log_tag))
|
||||
{
|
||||
result = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(private_log_tag, "log_set_global_tag failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int log_set_local_level_for_tag(const char *const tag, const ERROR_LEVEL level)
|
||||
{
|
||||
|
||||
ERROR_OUTPUT output = DEFAULT_ERROR_OUTPUT;
|
||||
return log_set_local_level_for_tag(tag, level, output);
|
||||
}
|
||||
|
||||
int log_set_local_level_for_tag(const char * const tag, const ERROR_LEVEL level,
|
||||
const ERROR_OUTPUT output)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
BREAK_IF_ZERO(2, tag);
|
||||
BREAK_IF_ZERO(3, global_log_mutex);
|
||||
BREAK_IF_ZERO(4, local_log_level_list);
|
||||
|
||||
AutoLock latch(global_log_mutex);
|
||||
|
||||
BREAK_IF_NON_ZERO(5, latch.ZeroIfLocked());
|
||||
|
||||
LocalLogLevelItem * const p_item = findLocalLevelItemLocked(tag);
|
||||
|
||||
if(0 != p_item)
|
||||
{
|
||||
p_item->setLevel(level);
|
||||
p_item->setOutput(output);
|
||||
}
|
||||
else
|
||||
{
|
||||
LocalLogLevelItem item(tag);
|
||||
item.setLevel(level);
|
||||
item.setOutput(output);
|
||||
BREAK_IF_ZERO(6, item.getTag());
|
||||
BREAK_IF_NON_ZERO(7, local_log_level_list->add(item));
|
||||
}
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(private_log_tag, "log_set_local_level_for_tag failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int log_flush_all_local_level()
|
||||
{
|
||||
return log_flush_local_level_for_tag(0);
|
||||
}
|
||||
|
||||
int log_flush_local_level_for_tag(const char * const tag)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
BREAK_IF_ZERO(2, global_log_mutex);
|
||||
BREAK_IF_ZERO(3, local_log_level_list)
|
||||
|
||||
AutoLock latch(global_log_mutex);
|
||||
|
||||
BREAK_IF_NON_ZERO(4, latch.ZeroIfLocked());
|
||||
|
||||
for (ListIterator<LocalLogLevelItem> it = local_log_level_list->begin(); it != local_log_level_list->end();)
|
||||
{
|
||||
if((0 == tag) || it->equals(tag))
|
||||
{
|
||||
it = local_log_level_list->erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(private_log_tag, "log_flush_local_level_for_tag failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void log_error_no_lock(const char * const local_log_tag, const char * const format, ...)
|
||||
{
|
||||
// note there is NO AUTO LOCK for this function
|
||||
// this function is designed to report WITHOUT any locks
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
// don't lock the global mutex, for we are reporting a bug in threading code
|
||||
vlog(local_log_tag, EL_ERROR, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_error(const char * const local_log_tag, const char * const format, ...)
|
||||
{
|
||||
// ignore null checking for global_log_mutex. let it fail and continue
|
||||
// there is something very wrong, but we still want to log message to be sent out
|
||||
AutoLock latch(global_log_mutex);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vlog(local_log_tag, EL_ERROR, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_warning(const char * const local_log_tag, const char * const format, ...)
|
||||
{
|
||||
// ignore null checking for global_log_mutex. let it fail and continue
|
||||
// there is something very wrong, but we still want to log message to be sent out
|
||||
AutoLock latch(global_log_mutex);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vlog(local_log_tag, EL_WARNING, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_info(const char * const local_log_tag, const char * const format, ...)
|
||||
{
|
||||
// ignore null checking for global_log_mutex. let it fail and continue
|
||||
// there is something very wrong, but we still want to log message to be sent out
|
||||
AutoLock latch(global_log_mutex);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vlog(local_log_tag, EL_INFO, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_debug(const char * const local_log_tag, const char * const format, ...)
|
||||
{
|
||||
// ignore null checking for global_log_mutex. let it fail and continue
|
||||
// there is something very wrong, but we still want to log message to be sent out
|
||||
AutoLock latch(global_log_mutex);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vlog(local_log_tag, EL_DEBUG, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void log_verbose(const char * const local_log_tag, const char * const format, ...)
|
||||
{
|
||||
// ignore null checking for global_log_mutex. let it fail and continue
|
||||
// there is something very wrong, but we still want to log message to be sent out
|
||||
AutoLock latch(global_log_mutex);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vlog(local_log_tag, EL_VERBOSE, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
366
qcom/opensource/location/utils/base_util/src/memorystream.cpp
Normal file
366
qcom/opensource/location/utils/base_util/src/memorystream.cpp
Normal file
@@ -0,0 +1,366 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Memory stream
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This component implements one input memory stream and one auto-expandable
|
||||
output memory stream.
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#include <new>
|
||||
#include <string.h>
|
||||
|
||||
#include <base_util/log.h>
|
||||
#include <base_util/memorystream.h>
|
||||
|
||||
#define BREAK_IF_ZERO(ERR,X) if(0==(X)) {result = (ERR); break;}
|
||||
#define BREAK_IF_NON_ZERO(ERR,X) if(0!=(X)) {result = (ERR); break;}
|
||||
#define BREAK_IF_NON_ZERO_RC(ERR,RC,X) if(0!=(RC=(X))) {result = (ERR); break;}
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
static const char * const TAG = "MemoryStream";
|
||||
|
||||
MemoryStreamBase::~MemoryStreamBase()
|
||||
{
|
||||
// dummy destructor
|
||||
}
|
||||
|
||||
OutMemoryStream::~OutMemoryStream()
|
||||
{
|
||||
// dummy destructor
|
||||
}
|
||||
|
||||
InMemoryStream::~InMemoryStream()
|
||||
{
|
||||
// dummy destructor
|
||||
}
|
||||
|
||||
class OutMemoryStreamImpl: public OutMemoryStream
|
||||
{
|
||||
public:
|
||||
OutMemoryStreamImpl();
|
||||
~OutMemoryStreamImpl();
|
||||
size_t getSize() const
|
||||
{
|
||||
return getPutCursor();
|
||||
}
|
||||
|
||||
BYTE * getBufferNonConst()
|
||||
{
|
||||
return m_pData;
|
||||
}
|
||||
|
||||
const BYTE * getBuffer() const
|
||||
{
|
||||
return m_pData;
|
||||
}
|
||||
|
||||
size_t getPutCursor() const
|
||||
{
|
||||
return m_put_cursor;
|
||||
}
|
||||
|
||||
int append(const void * const pData, const size_t length);
|
||||
|
||||
void releaseBufferOwnership()
|
||||
{
|
||||
m_pData = 0;
|
||||
m_put_cursor = 0;
|
||||
m_capacity = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
BYTE * m_pData;
|
||||
size_t m_put_cursor;
|
||||
size_t m_capacity;
|
||||
|
||||
static const size_t min_length = 64;
|
||||
int expand(const size_t length);
|
||||
};
|
||||
|
||||
OutMemoryStreamImpl::OutMemoryStreamImpl() :
|
||||
m_pData(0), m_put_cursor(0), m_capacity(0)
|
||||
{
|
||||
}
|
||||
|
||||
OutMemoryStreamImpl::~OutMemoryStreamImpl()
|
||||
{
|
||||
if(0 != m_pData)
|
||||
{
|
||||
delete[] m_pData;
|
||||
m_pData = 0;
|
||||
}
|
||||
m_put_cursor = 0;
|
||||
m_capacity = 0;
|
||||
}
|
||||
|
||||
int OutMemoryStreamImpl::expand(const size_t length)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(0 >= length)
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
const size_t space_left = m_capacity - m_put_cursor;
|
||||
if(length < space_left)
|
||||
{
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t new_length = m_put_cursor + length;
|
||||
if(new_length < min_length)
|
||||
{
|
||||
new_length = min_length;
|
||||
}
|
||||
else if(new_length < (m_capacity * 2))
|
||||
{
|
||||
new_length = m_capacity * 2;
|
||||
}
|
||||
|
||||
BYTE * new_buffer = new (std::nothrow) BYTE[new_length];
|
||||
|
||||
if(0 == new_buffer)
|
||||
{
|
||||
result = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
if(0 != m_pData)
|
||||
{
|
||||
memcpy(new_buffer, m_pData, m_put_cursor);
|
||||
delete[] m_pData;
|
||||
}
|
||||
m_pData = new_buffer;
|
||||
m_capacity = new_length;
|
||||
// m_put_cursor is not changed
|
||||
|
||||
//log_verbose(TAG, "stream expanded to %u bytes, with length %u", (unsigned int)m_capacity, (unsigned int)m_put_cursor);
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "expand error %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
int OutMemoryStreamImpl::append(const void * const pData, const size_t length)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(0 != expand(length))
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(m_pData + m_put_cursor, pData, length);
|
||||
m_put_cursor += length;
|
||||
|
||||
//log_verbose(TAG, "current stream length %u", (unsigned int)m_put_cursor);
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "append error %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class InMemoryStreamImpl: public InMemoryStream
|
||||
{
|
||||
public:
|
||||
InMemoryStreamImpl(OutMemoryStream * const os = 0);
|
||||
~InMemoryStreamImpl();
|
||||
size_t getSize() const
|
||||
{
|
||||
return getCapacity();
|
||||
}
|
||||
|
||||
const BYTE * getBuffer() const
|
||||
{
|
||||
return m_pData;
|
||||
}
|
||||
|
||||
int setBufferOwnership(const void ** const ppIn, const size_t length)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
BREAK_IF_ZERO(2, ppIn);
|
||||
|
||||
BREAK_IF_NON_ZERO(3, setBufferNoDup(*ppIn, length));
|
||||
*ppIn = 0;
|
||||
m_ownership = true;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "setBufferOwnership failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int setBufferNoDup(const void * const pIn, const size_t length)
|
||||
{
|
||||
if(m_ownership)
|
||||
{
|
||||
delete[] m_pData;
|
||||
m_ownership = false;
|
||||
}
|
||||
m_pData = reinterpret_cast<const BYTE*>(pIn);
|
||||
m_capacity = length;
|
||||
m_get_cursor = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int extract(void * const pData, const size_t length);
|
||||
|
||||
size_t getGetCursor() const
|
||||
{
|
||||
return m_get_cursor;
|
||||
}
|
||||
|
||||
size_t getCapacity() const
|
||||
{
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
int setGetCursor(const size_t cursor)
|
||||
{
|
||||
if(cursor <= m_capacity)
|
||||
{
|
||||
m_get_cursor = cursor;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "setGetCursor range error");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
virtual InMemoryStream * clone() const;
|
||||
|
||||
private:
|
||||
bool m_ownership;
|
||||
const BYTE * m_pData;
|
||||
size_t m_get_cursor;
|
||||
size_t m_capacity;
|
||||
};
|
||||
|
||||
InMemoryStreamImpl::InMemoryStreamImpl(OutMemoryStream * const os) :
|
||||
m_ownership(false), m_pData(0), m_get_cursor(0), m_capacity(0)
|
||||
{
|
||||
if(os != 0)
|
||||
{
|
||||
m_ownership = true;
|
||||
m_pData = os->getBuffer();
|
||||
m_capacity = os->getSize();
|
||||
static_cast<OutMemoryStreamImpl *>(os)->releaseBufferOwnership();
|
||||
}
|
||||
}
|
||||
|
||||
InMemoryStreamImpl::~InMemoryStreamImpl()
|
||||
{
|
||||
if(m_ownership)
|
||||
{
|
||||
delete[] m_pData;
|
||||
}
|
||||
m_pData = 0;
|
||||
m_get_cursor = 0;
|
||||
m_capacity = 0;
|
||||
}
|
||||
|
||||
int InMemoryStreamImpl::extract(void * const pData, const size_t length)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(0 == length)
|
||||
{
|
||||
result = 3;
|
||||
break;
|
||||
}
|
||||
if(0 == m_pData)
|
||||
{
|
||||
result = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
const size_t data_left = m_capacity - m_get_cursor;
|
||||
if(data_left < length)
|
||||
{
|
||||
result = 5;
|
||||
break;
|
||||
}
|
||||
|
||||
if(0 != pData)
|
||||
{
|
||||
memcpy(pData, m_pData + m_get_cursor, length);
|
||||
}
|
||||
m_get_cursor += length;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "extract error %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
OutMemoryStream * OutMemoryStream::createInstance()
|
||||
{
|
||||
return new (std::nothrow) OutMemoryStreamImpl();
|
||||
}
|
||||
|
||||
InMemoryStream * InMemoryStream::createInstance()
|
||||
{
|
||||
return new (std::nothrow) InMemoryStreamImpl();
|
||||
}
|
||||
|
||||
InMemoryStream * InMemoryStream::createInstance(OutMemoryStream * const os)
|
||||
{
|
||||
return new (std::nothrow) InMemoryStreamImpl(os);
|
||||
}
|
||||
|
||||
InMemoryStream * InMemoryStreamImpl::clone() const
|
||||
{
|
||||
InMemoryStreamImpl *pNewIs = (InMemoryStreamImpl *)InMemoryStream::createInstance();
|
||||
|
||||
if (NULL != pNewIs) {
|
||||
// do shallow copy first
|
||||
*pNewIs = *this;
|
||||
if (m_pData) {
|
||||
pNewIs->m_pData = new BYTE[m_capacity];
|
||||
if (pNewIs->m_pData) {
|
||||
memcpy((void *)pNewIs->m_pData, (const void *)m_pData, m_capacity);
|
||||
pNewIs->m_ownership = true;
|
||||
} else {
|
||||
delete pNewIs;
|
||||
pNewIs = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pNewIs;
|
||||
}
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
1169
qcom/opensource/location/utils/base_util/src/nvparam_mgr.cpp
Normal file
1169
qcom/opensource/location/utils/base_util/src/nvparam_mgr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1483
qcom/opensource/location/utils/base_util/src/postcard.cpp
Normal file
1483
qcom/opensource/location/utils/base_util/src/postcard.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,85 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
String related routines
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This component provides utilities used for string processing
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#include <string.h>
|
||||
|
||||
#include <base_util/log.h>
|
||||
|
||||
#ifndef IZAT_OFFLINE
|
||||
#define HAS_STRLCPY 1
|
||||
#endif // #ifndef IZAT_OFFLINE
|
||||
|
||||
#define BREAK_IF_ZERO(ERR,X) if(0==(X)) {result = (ERR); break;}
|
||||
#define BREAK_IF_NON_ZERO(ERR,X) if(0!=(X)) {result = (ERR); break;}
|
||||
#define BREAK_IF_NON_ZERO_RC(ERR,RC,X) if(0!=(RC=(X))) {result = (ERR); break;}
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
#if HAS_STRLCPY
|
||||
#else // #if HAS_STRLCPY
|
||||
size_t strlcpy(char *dest, const char *src, size_t dest_capacity)
|
||||
{
|
||||
// strlcpy is not available on standard linux glibc, so I have to
|
||||
// implement this
|
||||
// somehow Android has its own strlcpy
|
||||
size_t src_length = strlen(src);
|
||||
if(dest_capacity > 0)
|
||||
{
|
||||
size_t copy_length = 0;
|
||||
if(src_length >= dest_capacity)
|
||||
{
|
||||
copy_length = dest_capacity - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_length = src_length;
|
||||
}
|
||||
memcpy(dest, src, copy_length);
|
||||
dest[copy_length] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// weird error
|
||||
src_length = 0;
|
||||
}
|
||||
return src_length;
|
||||
}
|
||||
|
||||
size_t strlcat(char *dest, const char *src, size_t dest_capacity)
|
||||
{
|
||||
size_t dest_length = strlen(dest);
|
||||
size_t src_length = strlen(src);
|
||||
if (dest_capacity > 0)
|
||||
{
|
||||
size_t copy_length = 0;
|
||||
if (dest_length + src_length >= dest_capacity)
|
||||
{
|
||||
copy_length = dest_capacity - dest_length - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_length = src_length;
|
||||
}
|
||||
memcpy(dest + dest_length, src, copy_length);
|
||||
dest_length += copy_length;
|
||||
dest[dest_length] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// weird error
|
||||
dest_length = 0;
|
||||
}
|
||||
return dest_length;
|
||||
}
|
||||
#endif // #if HAS_STRLCPY
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
894
qcom/opensource/location/utils/base_util/src/sync.cpp
Normal file
894
qcom/opensource/location/utils/base_util/src/sync.cpp
Normal file
@@ -0,0 +1,894 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Sync utilities
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This component provides utilities used for synchronization among threads
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <new>
|
||||
|
||||
#include <base_util/queue.h>
|
||||
#include <base_util/log.h>
|
||||
#include <base_util/sync.h>
|
||||
|
||||
#define BREAK_IF_ZERO(ERR,X) if(0==(X)) {result = (ERR); break;}
|
||||
#define BREAK_IF_NON_ZERO(ERR,X) if(0!=(X)) {result = (ERR); break;}
|
||||
#define BREAK_IF_NON_ZERO_RC(ERR,RC,X) if(0!=(RC=(X))) {result = (ERR); break;}
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
// non-thread safe version, to be used only in threading related code
|
||||
void log_error_no_lock(const char * const local_log_tag, const char * const format, ...);
|
||||
|
||||
static const char * const MUTEX_DEFAULT_TAG = "Mutex";
|
||||
static const char * const AUTOLOCK_DEFAULT_TAG = "AutoLock";
|
||||
static const char * const WAITABLE_BASE_DEFAULT_TAG = "WaitableBase";
|
||||
static const char * const QUEUE_DEFAULT_TAG = "BlockingQueue";
|
||||
static const char * const THREAD_DEFAULT_TAG = "AutoLock";
|
||||
|
||||
class MutexImpl: public Mutex
|
||||
{
|
||||
public:
|
||||
MutexImpl(const char * const tag, const bool verboseLog);
|
||||
virtual ~MutexImpl();
|
||||
int lock();
|
||||
int unlock();
|
||||
|
||||
pthread_mutex_t * getRawMutex()
|
||||
{
|
||||
return &m_mutex;
|
||||
}
|
||||
private:
|
||||
|
||||
// this variable is only set once, at creation
|
||||
// after that, it can never change, for it is not protected by a mutex
|
||||
const char * m_tag;
|
||||
|
||||
// this variable is only set once, at creation
|
||||
// after that, it can never change, for it is not protected by a mutex
|
||||
const bool m_flagEnableVerboseLog;
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
};
|
||||
|
||||
MutexImpl::MutexImpl(const char * const tag, const bool verboseLog) :
|
||||
m_tag(tag),
|
||||
m_flagEnableVerboseLog(verboseLog)
|
||||
{
|
||||
int result = 1;
|
||||
pthread_mutexattr_t mutex_attr;
|
||||
bool destroy_attr = false;
|
||||
|
||||
do
|
||||
{
|
||||
if(0 == m_tag)
|
||||
{
|
||||
m_tag = MUTEX_DEFAULT_TAG;
|
||||
}
|
||||
BREAK_IF_NON_ZERO(2, pthread_mutexattr_init(&mutex_attr));
|
||||
destroy_attr = true;
|
||||
BREAK_IF_NON_ZERO(3, pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK));
|
||||
BREAK_IF_NON_ZERO(4, pthread_mutex_init(&m_mutex, &mutex_attr));
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if (destroy_attr == true)
|
||||
{
|
||||
if (0 != pthread_mutexattr_destroy(&mutex_attr))
|
||||
{
|
||||
result = 5;
|
||||
}
|
||||
}
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "MutexImpl: result: %d, error: %d, [%s]", result, errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
int rc = pthread_mutex_destroy(&m_mutex);
|
||||
if(0 != rc)
|
||||
{
|
||||
log_error_no_lock(m_tag, "~MutexImpl: pthread_mutex_destroy rc: %d, [%s]", rc, strerror(rc));
|
||||
}
|
||||
}
|
||||
|
||||
int MutexImpl::lock()
|
||||
{
|
||||
if(m_flagEnableVerboseLog)
|
||||
{
|
||||
log_verbose(m_tag, "lock: about to lock");
|
||||
}
|
||||
|
||||
int rc = pthread_mutex_lock(&m_mutex);
|
||||
if(0 != rc)
|
||||
{
|
||||
log_error_no_lock(m_tag, "lock: pthread_mutex_lock return code: %d, [%s]", rc, strerror(rc));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(m_flagEnableVerboseLog)
|
||||
{
|
||||
log_verbose(m_tag, "lock: just acquired");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MutexImpl::unlock()
|
||||
{
|
||||
if(0 != pthread_mutex_unlock(&m_mutex))
|
||||
{
|
||||
log_error_no_lock(m_tag, "unlock: pthread_mutex_unlock error: %d, [%s]", errno, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(m_flagEnableVerboseLog)
|
||||
{
|
||||
log_verbose(m_tag, "lock: just released");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
// dummy destructor
|
||||
}
|
||||
|
||||
Mutex * Mutex::createInstance(const char * const tag, const bool verboseLog)
|
||||
{
|
||||
return new (std::nothrow) MutexImpl(tag, verboseLog);
|
||||
}
|
||||
|
||||
AutoLock::AutoLock(Mutex * const pMutex, const char * log_tag) :
|
||||
m_pMutex(pMutex),
|
||||
m_tag(log_tag),
|
||||
m_locked(false)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(0 == m_tag)
|
||||
{
|
||||
m_tag = AUTOLOCK_DEFAULT_TAG;
|
||||
}
|
||||
|
||||
BREAK_IF_ZERO(2, m_pMutex);
|
||||
|
||||
BREAK_IF_NON_ZERO(3, m_pMutex->lock());
|
||||
|
||||
m_locked = true;
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "AutoLock: lock error: %d", result);
|
||||
}
|
||||
}
|
||||
|
||||
AutoLock::~AutoLock()
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
BREAK_IF_ZERO(2, m_pMutex);
|
||||
|
||||
if (m_locked)
|
||||
{
|
||||
// Do not unlock the lock if we haven't acquired it.
|
||||
BREAK_IF_NON_ZERO(3, m_pMutex->unlock());
|
||||
}
|
||||
|
||||
m_locked = false;
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "AutoLock: unlock error: %d", result);
|
||||
}
|
||||
}
|
||||
|
||||
int AutoLock::ZeroIfLocked()
|
||||
{
|
||||
if(m_locked)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
class WaitableBase
|
||||
{
|
||||
public:
|
||||
virtual int lock_and_wait(const TimeDiff & timeout_diff);
|
||||
virtual int unlock();
|
||||
|
||||
WaitableBase(const char * const name, const bool verboseLog);
|
||||
virtual ~WaitableBase() = 0;
|
||||
|
||||
// the call flow for internal state modification should be
|
||||
// 'lock' -> modify state -> 'signal_one_and_then_unlock'
|
||||
virtual int lock();
|
||||
virtual int signal_one_and_then_unlock();
|
||||
virtual int signal_all_and_then_unlock();
|
||||
|
||||
// called by lock_and_wait to make sure we need to wait after
|
||||
// locked but before the wait
|
||||
virtual int ZeroIfShouldWaitAgain_locked() = 0;
|
||||
private:
|
||||
pthread_cond_t m_cond;
|
||||
MutexImpl m_mutex;
|
||||
const char * m_tag;
|
||||
bool m_verboseLog;
|
||||
};
|
||||
|
||||
WaitableBase::WaitableBase(const char * const name, const bool verboseLog) :
|
||||
m_mutex(name, verboseLog),
|
||||
m_tag(name),
|
||||
m_verboseLog(verboseLog)
|
||||
{
|
||||
int result = 1;
|
||||
pthread_condattr_t cond_attr;
|
||||
bool destroy_cond = false;
|
||||
|
||||
do
|
||||
{
|
||||
if(0 == m_tag)
|
||||
{
|
||||
m_tag = WAITABLE_BASE_DEFAULT_TAG;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
BREAK_IF_NON_ZERO(2, pthread_condattr_init(&cond_attr));
|
||||
destroy_cond = true;
|
||||
|
||||
BREAK_IF_NON_ZERO(3, pthread_condattr_setclock(&cond_attr, CLOCK_REALTIME));
|
||||
|
||||
BREAK_IF_NON_ZERO(4, pthread_cond_init(&m_cond, &cond_attr));
|
||||
|
||||
result = 0;
|
||||
} while(0);
|
||||
|
||||
if (destroy_cond == true)
|
||||
{
|
||||
if (0 != pthread_condattr_destroy(&cond_attr))
|
||||
{
|
||||
result = 5;
|
||||
}
|
||||
}
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "WaitableBase: pthread conditional variable error: %d, errno=%d, [%s]",
|
||||
result, errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
WaitableBase::~WaitableBase()
|
||||
{
|
||||
if(0 != pthread_cond_destroy(&m_cond))
|
||||
{
|
||||
log_error_no_lock(m_tag, "~WaitableBase: pthread_cond_destroy error: %d, [%s]", errno, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
int WaitableBase::lock()
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(m_verboseLog)
|
||||
{
|
||||
log_verbose(m_tag, "about to lock for state modification");
|
||||
}
|
||||
|
||||
// if we're locked, we should not lock again
|
||||
BREAK_IF_NON_ZERO(3, m_mutex.lock());
|
||||
|
||||
if(m_verboseLog)
|
||||
{
|
||||
log_verbose(m_tag, "just acquired lock for state modification");
|
||||
}
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "lock : result %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int WaitableBase::unlock()
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
// if we're not locked, we should not unlock again
|
||||
|
||||
if(m_verboseLog)
|
||||
{
|
||||
log_verbose(m_tag, "about to unlock");
|
||||
}
|
||||
|
||||
BREAK_IF_NON_ZERO(3, m_mutex.unlock());
|
||||
|
||||
if(m_verboseLog)
|
||||
{
|
||||
log_verbose(m_tag, "unlocked");
|
||||
}
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "unlock : result %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int WaitableBase::signal_one_and_then_unlock()
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
// we should be already locked
|
||||
|
||||
if(m_verboseLog)
|
||||
{
|
||||
log_verbose(m_tag, "about to signal");
|
||||
}
|
||||
|
||||
result = 100;
|
||||
if(0 != pthread_cond_signal(&m_cond))
|
||||
{
|
||||
result = 101;
|
||||
}
|
||||
|
||||
BREAK_IF_NON_ZERO(4, unlock());
|
||||
|
||||
if(100 != result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "WaitableBase: signal_one_and_then_unlock result: %d, errno %d, [%s]", result, errno,
|
||||
strerror(errno));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int WaitableBase::signal_all_and_then_unlock()
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
// we should be already locked
|
||||
|
||||
if(m_verboseLog)
|
||||
{
|
||||
log_verbose(m_tag, "about to signal");
|
||||
}
|
||||
|
||||
result = 100;
|
||||
if(0 != pthread_cond_broadcast(&m_cond))
|
||||
{
|
||||
result = 101;
|
||||
}
|
||||
|
||||
BREAK_IF_NON_ZERO(4, unlock());
|
||||
|
||||
if(100 != result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "WaitableBase: signal_all_and_then_unlock result: %d, errno: %d, [%s]", result, errno,
|
||||
strerror(errno));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int WaitableBase::lock_and_wait(const TimeDiff & timeout_diff)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
// we should not be already locked
|
||||
|
||||
if(m_verboseLog)
|
||||
{
|
||||
log_verbose(m_tag, "about to lock for wait");
|
||||
}
|
||||
|
||||
BREAK_IF_NON_ZERO(2, m_mutex.lock());
|
||||
|
||||
bool flagTimeout = false;
|
||||
result = 10;
|
||||
// if this function returns non-zero, we return 0 immediately without waiting
|
||||
while ((!flagTimeout) && (0 == ZeroIfShouldWaitAgain_locked()))
|
||||
{
|
||||
|
||||
if(m_verboseLog)
|
||||
{
|
||||
log_verbose(m_tag, "about to wait");
|
||||
}
|
||||
|
||||
int rc = 0;
|
||||
if(!timeout_diff.is_valid())
|
||||
{
|
||||
// timeout is invalid, which means we are going to wait forever
|
||||
rc = pthread_cond_wait(&m_cond, m_mutex.getRawMutex());
|
||||
}
|
||||
else
|
||||
{
|
||||
// same pthread_cond_timedwait, but now time should be absolute realtime time
|
||||
const Timestamp now_realtime(CLOCK_REALTIME);
|
||||
Timestamp timeout_realtime(now_realtime + timeout_diff);
|
||||
if (!timeout_realtime.is_valid())
|
||||
{
|
||||
// this shall not happen
|
||||
result = 12;
|
||||
break;
|
||||
}
|
||||
if(timeout_diff.get_total_sec() > 0)
|
||||
{
|
||||
rc = pthread_cond_timedwait(&m_cond, m_mutex.getRawMutex(),
|
||||
timeout_realtime.getTimestampPtr());
|
||||
}
|
||||
else
|
||||
{
|
||||
// removing the timeout parameter - essentially making value of zero
|
||||
rc = pthread_cond_timedwait(&m_cond, m_mutex.getRawMutex(),
|
||||
now_realtime.getTimestampPtr());
|
||||
}
|
||||
}
|
||||
|
||||
if(m_verboseLog)
|
||||
{
|
||||
log_verbose(m_tag, "just waken up from wait");
|
||||
}
|
||||
|
||||
if(0 == rc)
|
||||
{
|
||||
// good
|
||||
}
|
||||
else if(ETIMEDOUT == rc)
|
||||
{
|
||||
// timeout_diff
|
||||
flagTimeout = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// something is wrong
|
||||
log_error_no_lock(m_tag, "lock_and_wait: pthread_cond_wait error: %d, [%s]", errno, strerror(errno));
|
||||
result = 15;
|
||||
}
|
||||
|
||||
if(10 != result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(10 != result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "WaitableBase: lock_and_wait error: %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
BlockingQueue::~BlockingQueue()
|
||||
{
|
||||
// dummy destructor
|
||||
}
|
||||
|
||||
class BlockingQueueImpl: public BlockingQueue, protected WaitableBase
|
||||
{
|
||||
public:
|
||||
BlockingQueueImpl(const char * tag, const bool verboseLog);
|
||||
~BlockingQueueImpl();
|
||||
|
||||
virtual int push(void * const ptr);
|
||||
virtual int close();
|
||||
virtual int pop(void ** const pptr, const timespec * const timeout_abs_realtime, bool * const p_is_queue_closed);
|
||||
virtual int pop(void ** const pptr, const TimeDiff & timeout, bool * const p_is_queue_closed);
|
||||
|
||||
virtual int ZeroIfShouldWaitAgain_locked();
|
||||
|
||||
Queue<void *> m_queue;
|
||||
const char * m_tag;
|
||||
bool m_isClosed;
|
||||
bool m_verboseLog;
|
||||
};
|
||||
|
||||
BlockingQueueImpl::BlockingQueueImpl(const char * tag, const bool verboseLog) :
|
||||
WaitableBase("BlockingQueue", verboseLog),
|
||||
m_tag(tag),
|
||||
m_isClosed(false),
|
||||
m_verboseLog(verboseLog)
|
||||
{
|
||||
if(0 == m_tag)
|
||||
{
|
||||
m_tag = QUEUE_DEFAULT_TAG;
|
||||
}
|
||||
}
|
||||
|
||||
BlockingQueueImpl::~BlockingQueueImpl()
|
||||
{
|
||||
if(m_queue.getSize() > 0)
|
||||
{
|
||||
log_warning(m_tag, "~BlockingQueueImpl: memory leak");
|
||||
}
|
||||
}
|
||||
|
||||
int BlockingQueueImpl::ZeroIfShouldWaitAgain_locked()
|
||||
{
|
||||
if(m_isClosed)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_queue.getSize();
|
||||
}
|
||||
}
|
||||
|
||||
int BlockingQueueImpl::push(void * const ptr)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
BREAK_IF_NON_ZERO(2, lock());
|
||||
|
||||
if(m_isClosed)
|
||||
{
|
||||
result = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 100;
|
||||
if(0 != m_queue.push(ptr))
|
||||
{
|
||||
// something is wrong, but we cannot leave just now
|
||||
result = 101;
|
||||
}
|
||||
}
|
||||
|
||||
BREAK_IF_NON_ZERO(4, signal_one_and_then_unlock());
|
||||
|
||||
if(100 != result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "push: error: %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int BlockingQueueImpl::close()
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
BREAK_IF_NON_ZERO(2, lock());
|
||||
m_isClosed = true;
|
||||
// note we have to release ALL threads blocking on us
|
||||
BREAK_IF_NON_ZERO(3, signal_all_and_then_unlock());
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "close: error: %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int BlockingQueueImpl::pop(void ** const pptr, const timespec * const timeout_abs_realtime, bool * const p_is_queue_closed)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
// warn the API user about deprecated feature
|
||||
log_warning(m_tag, "pop 0: deprecated.");
|
||||
|
||||
BREAK_IF_ZERO(2, pptr);
|
||||
*pptr = 0;
|
||||
|
||||
const Timestamp now_wallclock(CLOCK_REALTIME);
|
||||
TimeDiff timeout_diff(false);
|
||||
if(0 != timeout_abs_realtime)
|
||||
{
|
||||
const Timestamp timeout_wallclock(CLOCK_REALTIME, *timeout_abs_realtime);
|
||||
if(timeout_wallclock >= now_wallclock)
|
||||
{
|
||||
timeout_diff = timeout_wallclock - now_wallclock;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is valid 0, which means we are not going to wait at all
|
||||
timeout_diff.reset(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// timeout_diff is reset to invalid, which means we are going to wait forever
|
||||
timeout_diff.reset(false);
|
||||
}
|
||||
|
||||
BREAK_IF_NON_ZERO(10, pop(pptr, timeout_diff, p_is_queue_closed));
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "pop 0: error: %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int BlockingQueueImpl::pop(void ** const pptr, const TimeDiff & timeout, bool * const p_is_queue_closed)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
BREAK_IF_ZERO(2, pptr);
|
||||
*pptr = 0;
|
||||
|
||||
if(0 != p_is_queue_closed)
|
||||
{
|
||||
*p_is_queue_closed = false;
|
||||
}
|
||||
|
||||
BREAK_IF_NON_ZERO(4, lock_and_wait(timeout));
|
||||
|
||||
// note we're now locked, so it's okay to copy the members
|
||||
if(0 != p_is_queue_closed)
|
||||
{
|
||||
*p_is_queue_closed = m_isClosed;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_isClosed)
|
||||
{
|
||||
// warn to API user that he/she should provide p_is_queue_closed for us
|
||||
// to notify this condition
|
||||
log_warning(m_tag, "pop: queue is already closed");
|
||||
}
|
||||
else
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
if(m_queue.getSize() > 0)
|
||||
{
|
||||
if(0 != m_queue.pop(pptr))
|
||||
{
|
||||
// something is wrong, but we cannot leave just now
|
||||
result = 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// timeout or queue closed
|
||||
}
|
||||
|
||||
BREAK_IF_NON_ZERO(5, unlock());
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "pop: error: %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
BlockingQueue * BlockingQueue::createInstance(const char * tag, const bool verboseLog)
|
||||
{
|
||||
return new (std::nothrow) BlockingQueueImpl(tag, verboseLog);
|
||||
}
|
||||
|
||||
Runnable::~Runnable()
|
||||
{
|
||||
// dummy destructor
|
||||
}
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
// dummy destructor
|
||||
}
|
||||
|
||||
class ThreadImpl: public Thread
|
||||
{
|
||||
public:
|
||||
ThreadImpl(const char * tag, Runnable * const pRunnable, const bool delete_runnable_at_destruction);
|
||||
virtual ~ThreadImpl();
|
||||
virtual int launch();
|
||||
virtual int join();
|
||||
|
||||
const char * m_tag;
|
||||
Runnable * m_pRunnable;
|
||||
pthread_t m_thread;
|
||||
bool m_delete_runnable_at_destruction;
|
||||
|
||||
enum ThreadState
|
||||
{
|
||||
TS_NOT_CREATED_YET, TS_LAUNCHED_JOINABLE, TS_JOINED, TS_DETACHED,
|
||||
};
|
||||
ThreadState m_state;
|
||||
|
||||
static void * thread_func(void * ptr);
|
||||
};
|
||||
|
||||
ThreadImpl::~ThreadImpl()
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case TS_NOT_CREATED_YET:
|
||||
case TS_JOINED:
|
||||
case TS_DETACHED:
|
||||
// we're okay to leave
|
||||
if(m_delete_runnable_at_destruction)
|
||||
{
|
||||
delete m_pRunnable;
|
||||
}
|
||||
m_pRunnable = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error_no_lock(m_tag, "~ThreadImpl: thread is probably still running");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ThreadImpl::ThreadImpl(const char * tag, Runnable * const pRunnable, const bool delete_runnable_at_destruction) :
|
||||
m_tag(tag),
|
||||
m_pRunnable(pRunnable),
|
||||
m_delete_runnable_at_destruction(delete_runnable_at_destruction),
|
||||
m_state(TS_NOT_CREATED_YET)
|
||||
{
|
||||
// KlocWorks complains about m_thread not initialized
|
||||
memset(&m_thread, 0, sizeof(m_thread));
|
||||
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(0 == m_tag)
|
||||
{
|
||||
m_tag = THREAD_DEFAULT_TAG;
|
||||
}
|
||||
|
||||
BREAK_IF_ZERO(2, m_pRunnable);
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "ThreadImpl: result: %d", result);
|
||||
}
|
||||
}
|
||||
|
||||
int ThreadImpl::launch()
|
||||
{
|
||||
int result = 1;
|
||||
pthread_attr_t thread_attr;
|
||||
bool destroy_attr = false;
|
||||
|
||||
do
|
||||
{
|
||||
if(TS_NOT_CREATED_YET != m_state)
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
BREAK_IF_NON_ZERO(3, pthread_attr_init(&thread_attr));
|
||||
destroy_attr = true;
|
||||
// this is actually the default setting
|
||||
BREAK_IF_NON_ZERO(4, pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_JOINABLE));
|
||||
BREAK_IF_NON_ZERO(5, pthread_create(&m_thread, &thread_attr, thread_func, this));
|
||||
BREAK_IF_NON_ZERO(5, pthread_setname_np(m_thread, "loc-mq-thread"));
|
||||
m_state = TS_LAUNCHED_JOINABLE;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if (destroy_attr == true)
|
||||
{
|
||||
if (0 != pthread_attr_destroy(&thread_attr))
|
||||
{
|
||||
result = 5;
|
||||
}
|
||||
}
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "launch: result: %d, errno: %d, [%s]", result, errno, strerror(errno));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ThreadImpl::join()
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(TS_LAUNCHED_JOINABLE != m_state)
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// thread must have been created
|
||||
// thread must be joinable, not detached, for this to work
|
||||
void * ptr = 0;
|
||||
BREAK_IF_NON_ZERO(3, pthread_join(m_thread, &ptr));
|
||||
|
||||
m_state = TS_JOINED;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error_no_lock(m_tag, "join: result: %d, errno: %d, [%s]", result, errno, strerror(errno));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void * ThreadImpl::thread_func(void * ptr)
|
||||
{
|
||||
ThreadImpl * obj = reinterpret_cast<ThreadImpl *>(ptr);
|
||||
obj->m_pRunnable->run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Thread * Thread::createInstance(const char * tag, Runnable * const pRunnable, const bool delete_runnable_at_destruction)
|
||||
{
|
||||
return new (std::nothrow) ThreadImpl(tag, pRunnable, delete_runnable_at_destruction);
|
||||
}
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
696
qcom/opensource/location/utils/base_util/src/time_routines.cpp
Normal file
696
qcom/opensource/location/utils/base_util/src/time_routines.cpp
Normal file
@@ -0,0 +1,696 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Time related routines
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This component provides utilities used for timestamp and time
|
||||
difference processing
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <base_util/time_routines.h>
|
||||
#include <base_util/log.h>
|
||||
|
||||
#define BREAK_IF_ZERO(ERR,X) if(0==(X)) {result = (ERR); break;}
|
||||
#define BREAK_IF_NON_ZERO(ERR,X) if(0!=(X)) {result = (ERR); break;}
|
||||
#define BREAK_IF_NON_ZERO_RC(ERR,RC,X) if(0!=(RC=(X))) {result = (ERR); break;}
|
||||
|
||||
#ifdef CLOCK_BOOTTIME
|
||||
#define ENABLED_BOOTTIME_SUPPORT 1
|
||||
#else
|
||||
#define ENABLED_BOOTTIME_SUPPORT 0
|
||||
#endif
|
||||
|
||||
#define TIME_RTC_MS_AS_OF_12_1_2014 (1417569370000)
|
||||
|
||||
const int NANO_PER_SEC = 1000000000;
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
const char * const TimeDiff::TAG = "TimerDiff";
|
||||
const char * const Timestamp::TAG = "Timestamp";
|
||||
|
||||
TimeDiff::TimeDiff(const bool validity)
|
||||
{
|
||||
reset(validity);
|
||||
}
|
||||
|
||||
void TimeDiff::reset(const bool validity)
|
||||
{
|
||||
m_is_valid = validity;
|
||||
memset(&m_timediff, 0, sizeof(m_timediff));
|
||||
}
|
||||
|
||||
bool TimeDiff::is_valid() const
|
||||
{
|
||||
return m_is_valid;
|
||||
}
|
||||
|
||||
const timespec * TimeDiff::getTimeDiffPtr() const
|
||||
{
|
||||
if(!m_is_valid)
|
||||
{
|
||||
log_warning(TAG, "getTimeDiffPtr time diff is invalid");
|
||||
}
|
||||
return &m_timediff;
|
||||
}
|
||||
|
||||
float TimeDiff::get_total_sec() const
|
||||
{
|
||||
float conv = -1;
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_is_valid)
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
conv = m_timediff.tv_nsec / 1e9;
|
||||
conv += m_timediff.tv_sec;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "get_total_sec failed %d", result);
|
||||
}
|
||||
return conv;
|
||||
}
|
||||
|
||||
float TimeDiff::get_total_msec() const
|
||||
{
|
||||
float conv = -1;
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_is_valid)
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
conv = m_timediff.tv_nsec / 1e6f;
|
||||
conv += (m_timediff.tv_sec) * 1000.0f;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "get_total_msec failed %d", result);
|
||||
}
|
||||
return conv;
|
||||
}
|
||||
|
||||
int TimeDiff::add_sec(const int sec)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_is_valid)
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
m_timediff.tv_sec += sec;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "add_sec failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int TimeDiff::add_msec(const int msec)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_is_valid)
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
int sec = msec / 1000;
|
||||
long long int msec_modified = msec - sec * 1000;
|
||||
|
||||
m_timediff.tv_nsec += msec_modified * 1000000;
|
||||
|
||||
while (m_timediff.tv_nsec >= NANO_PER_SEC)
|
||||
{
|
||||
++sec;
|
||||
m_timediff.tv_nsec -= NANO_PER_SEC;
|
||||
}
|
||||
|
||||
m_timediff.tv_sec += sec;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "add_msec failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int TimeDiff::add_nsec(const int nsec)
|
||||
{
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_is_valid)
|
||||
{
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
m_timediff.tv_nsec += nsec;
|
||||
while (m_timediff.tv_nsec >= NANO_PER_SEC)
|
||||
{
|
||||
++m_timediff.tv_sec;
|
||||
m_timediff.tv_nsec -= NANO_PER_SEC;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "add_nsec failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Timestamp::Timestamp(bool set_to_default_clock)
|
||||
{
|
||||
invalidate();
|
||||
if(set_to_default_clock)
|
||||
{
|
||||
(void) reset_to_default_clock();
|
||||
}
|
||||
}
|
||||
|
||||
Timestamp::Timestamp(const int clock_id, const timespec & src)
|
||||
{
|
||||
m_is_valid = true;
|
||||
m_clock_id = clock_id;
|
||||
memcpy(&m_timestamp, &src, sizeof(m_timestamp));
|
||||
}
|
||||
|
||||
Timestamp::Timestamp(const Timestamp & rhs)
|
||||
{
|
||||
*this = rhs;
|
||||
}
|
||||
|
||||
Timestamp::Timestamp(const int clock_id)
|
||||
{
|
||||
reset_to_clock_id(clock_id);
|
||||
}
|
||||
|
||||
int Timestamp::get_clock_id() const
|
||||
{
|
||||
return m_clock_id;
|
||||
}
|
||||
|
||||
bool Timestamp::is_valid() const
|
||||
{
|
||||
return m_is_valid;
|
||||
}
|
||||
|
||||
bool Timestamp::is_valid_and_default() const
|
||||
{
|
||||
bool result = false;
|
||||
if(is_valid())
|
||||
{
|
||||
#if ENABLED_BOOTTIME_SUPPORT
|
||||
const int default_clock_id = CLOCK_BOOTTIME;
|
||||
#else
|
||||
const int default_clock_id = CLOCK_MONOTONIC;
|
||||
#endif //#if ENABLED_BOOTTIME_SUPPORT
|
||||
if(default_clock_id == m_clock_id)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Timestamp::invalidate()
|
||||
{
|
||||
m_is_valid = false;
|
||||
m_clock_id = -1;
|
||||
memset(&m_timestamp, 0, sizeof(m_timestamp));
|
||||
}
|
||||
|
||||
timespec * Timestamp::getTimestampPtr()
|
||||
{
|
||||
const timespec * const ptr = static_cast<const Timestamp *>(this)->getTimestampPtr();
|
||||
return const_cast<timespec *>(ptr);
|
||||
}
|
||||
|
||||
const timespec * Timestamp::getTimestampPtr() const
|
||||
{
|
||||
if(!m_is_valid)
|
||||
{
|
||||
log_warning(TAG, "getTimestampPtr timestamp is invalid");
|
||||
}
|
||||
return &m_timestamp;
|
||||
}
|
||||
|
||||
int Timestamp::reset_to_default_clock()
|
||||
{
|
||||
#if ENABLED_BOOTTIME_SUPPORT
|
||||
return reset_to_boottime();
|
||||
#else
|
||||
return reset_to_monotonic();
|
||||
#endif
|
||||
}
|
||||
|
||||
int Timestamp::reset_to_monotonic()
|
||||
{
|
||||
return reset_to_clock_id(CLOCK_MONOTONIC);
|
||||
}
|
||||
|
||||
int Timestamp::reset_to_boottime()
|
||||
{
|
||||
#if ENABLED_BOOTTIME_SUPPORT
|
||||
return reset_to_clock_id(CLOCK_BOOTTIME);
|
||||
#else
|
||||
invalidate();
|
||||
log_error(TAG, "reset_to_boottime not supported");
|
||||
return 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
int Timestamp::reset_to_realtime()
|
||||
{
|
||||
return reset_to_clock_id(CLOCK_REALTIME);
|
||||
}
|
||||
|
||||
int Timestamp::reset_to_clock_id(const int clock_id)
|
||||
{
|
||||
invalidate();
|
||||
if(0 == clock_gettime(clock_id, &m_timestamp))
|
||||
{
|
||||
m_clock_id = clock_id;
|
||||
m_is_valid = true;
|
||||
return 0;
|
||||
}
|
||||
log_error(TAG, "reset_to_clock_id failed: id(%d) errno(%d)(%s)", clock_id, errno, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
Timestamp Timestamp::operator -(const TimeDiff & rhs) const
|
||||
{
|
||||
Timestamp past(false);
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_is_valid)
|
||||
{
|
||||
result = 2;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(!rhs.is_valid())
|
||||
{
|
||||
result = 3;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
const timespec * rhs_ptr = rhs.getTimeDiffPtr();
|
||||
|
||||
past.m_timestamp.tv_sec = m_timestamp.tv_sec - rhs_ptr->tv_sec;
|
||||
past.m_timestamp.tv_nsec = m_timestamp.tv_nsec - rhs_ptr->tv_nsec;
|
||||
|
||||
while (past.m_timestamp.tv_nsec < 0)
|
||||
{
|
||||
--past.m_timestamp.tv_sec;
|
||||
past.m_timestamp.tv_nsec += NANO_PER_SEC;
|
||||
}
|
||||
while (past.m_timestamp.tv_nsec >= NANO_PER_SEC)
|
||||
{
|
||||
++past.m_timestamp.tv_sec;
|
||||
past.m_timestamp.tv_nsec -= NANO_PER_SEC;
|
||||
}
|
||||
|
||||
if(past.m_timestamp.tv_sec < 0)
|
||||
{
|
||||
log_error(TAG, "diff is returning -ve value possible time rollover %d", past.m_timestamp.tv_sec);
|
||||
}
|
||||
|
||||
past.m_is_valid = true;
|
||||
past.m_clock_id = m_clock_id;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "operator - diff failed %d", result);
|
||||
}
|
||||
return past;
|
||||
}
|
||||
|
||||
Timestamp Timestamp::operator +(const TimeDiff & rhs) const
|
||||
{
|
||||
Timestamp sum(false);
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_is_valid)
|
||||
{
|
||||
result = 2;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(!rhs.is_valid())
|
||||
{
|
||||
result = 3;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
const timespec * rhs_ptr = rhs.getTimeDiffPtr();
|
||||
|
||||
sum.m_timestamp.tv_sec = m_timestamp.tv_sec + rhs_ptr->tv_sec;
|
||||
sum.m_timestamp.tv_nsec = m_timestamp.tv_nsec + rhs_ptr->tv_nsec;
|
||||
|
||||
while (sum.m_timestamp.tv_nsec >= NANO_PER_SEC)
|
||||
{
|
||||
++sum.m_timestamp.tv_sec;
|
||||
sum.m_timestamp.tv_nsec -= NANO_PER_SEC;
|
||||
}
|
||||
sum.m_is_valid = true;
|
||||
sum.m_clock_id = m_clock_id;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "operator + failed %d", result);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
TimeDiff Timestamp::operator -(const Timestamp & rhs) const
|
||||
{
|
||||
// reset to invalid
|
||||
TimeDiff delta(false);
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_is_valid)
|
||||
{
|
||||
result = 2;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(!rhs.is_valid())
|
||||
{
|
||||
result = 3;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(m_clock_id != rhs.m_clock_id)
|
||||
{
|
||||
// must be the same clock !
|
||||
result = 4;
|
||||
log_error(TAG, "operator - ts: my clock id: %d, his clock id: %d", m_clock_id, rhs.m_clock_id);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
struct timespec time_delta = {};
|
||||
time_delta.tv_sec = m_timestamp.tv_sec - rhs.m_timestamp.tv_sec;
|
||||
time_delta.tv_nsec = m_timestamp.tv_nsec - rhs.m_timestamp.tv_nsec;
|
||||
|
||||
while (time_delta.tv_nsec < 0)
|
||||
{
|
||||
--time_delta.tv_sec;
|
||||
time_delta.tv_nsec += NANO_PER_SEC;
|
||||
}
|
||||
|
||||
while (time_delta.tv_nsec >= NANO_PER_SEC)
|
||||
{
|
||||
++time_delta.tv_sec;
|
||||
time_delta.tv_nsec -= NANO_PER_SEC;
|
||||
}
|
||||
|
||||
if(time_delta.tv_sec < 0)
|
||||
{
|
||||
log_error(TAG, "operator - ts returning -ve value probable time rollover: sec:%d/%d/%d, nsec:%d/%d/%d", (int) m_timestamp.tv_sec,
|
||||
(int) rhs.m_timestamp.tv_sec, (int) time_delta.tv_sec, (int) m_timestamp.tv_nsec,
|
||||
(int) rhs.m_timestamp.tv_nsec, (int) time_delta.tv_nsec);
|
||||
}
|
||||
|
||||
// set the diff to valid now
|
||||
delta.reset(true);
|
||||
BREAK_IF_NON_ZERO(10, delta.add_sec(time_delta.tv_sec));
|
||||
BREAK_IF_NON_ZERO(11, delta.add_nsec(time_delta.tv_nsec));
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "operator - ts failed %d", result);
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
|
||||
bool Timestamp::operator >=(const Timestamp & rhs) const
|
||||
{
|
||||
bool is_greater_then = false;
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
if(!m_is_valid)
|
||||
{
|
||||
result = 2;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(!rhs.is_valid())
|
||||
{
|
||||
result = 3;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(m_clock_id != rhs.m_clock_id)
|
||||
{
|
||||
// must be the same clock !
|
||||
result = 4;
|
||||
log_error(TAG, "operator >=: my clock id: %d, his clock id: %d", m_clock_id, rhs.m_clock_id);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
struct timespec time_delta = {};
|
||||
time_delta.tv_sec = m_timestamp.tv_sec - rhs.m_timestamp.tv_sec;
|
||||
time_delta.tv_nsec = m_timestamp.tv_nsec - rhs.m_timestamp.tv_nsec;
|
||||
|
||||
while (time_delta.tv_nsec < 0)
|
||||
{
|
||||
--time_delta.tv_sec;
|
||||
time_delta.tv_nsec += NANO_PER_SEC;
|
||||
}
|
||||
|
||||
while (time_delta.tv_nsec >= NANO_PER_SEC)
|
||||
{
|
||||
++time_delta.tv_sec;
|
||||
time_delta.tv_nsec -= NANO_PER_SEC;
|
||||
}
|
||||
|
||||
if(time_delta.tv_sec < 0)
|
||||
{
|
||||
is_greater_then = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_greater_then = true;
|
||||
}
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "operator >= failed %d", result);
|
||||
}
|
||||
return is_greater_then;
|
||||
}
|
||||
|
||||
bool Timestamp::operator <(const Timestamp & rhs) const
|
||||
{
|
||||
return !operator >=(rhs);
|
||||
}
|
||||
|
||||
Timestamp & Timestamp::operator =(const Timestamp & rhs)
|
||||
{
|
||||
m_is_valid = rhs.m_is_valid;
|
||||
m_clock_id = rhs.m_clock_id;
|
||||
m_timestamp = rhs.m_timestamp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int Timestamp::insert_into_postcard(OutPostcard * const dest_card, const char * const name_str)
|
||||
{
|
||||
OutPostcard * nest_card = 0;
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
BREAK_IF_ZERO(2, name_str);
|
||||
|
||||
nest_card = OutPostcard::createInstance();
|
||||
BREAK_IF_ZERO(3, nest_card);
|
||||
|
||||
if(!m_is_valid)
|
||||
{
|
||||
result = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
BREAK_IF_NON_ZERO(10, nest_card->init());
|
||||
// note that CLOCK_ID is system-specific. For example, you cannot find clock id concept in Java
|
||||
// on Android, there is SystemClock.elapsedRealtimeNanos which seemingly returns CLOCK_BOOTTIME,
|
||||
// but that is not really documented, so clock id becomes undefined in Java world anywhere
|
||||
// so, timestamp doesn't really work if your message has any chance of being interpreted from
|
||||
// the Java world (of Android)
|
||||
BREAK_IF_NON_ZERO(11, nest_card->addInt32("CLOCK_ID", m_clock_id));
|
||||
BREAK_IF_NON_ZERO(12, nest_card->addInt32("TS_SEC", (OutPostcard::INT32 )m_timestamp.tv_sec));
|
||||
BREAK_IF_NON_ZERO(13, nest_card->addInt32("TS_NSEC", (OutPostcard::INT32 )m_timestamp.tv_nsec));
|
||||
BREAK_IF_NON_ZERO(14, nest_card->finalize());
|
||||
BREAK_IF_NON_ZERO(20, dest_card->addCard(name_str, nest_card));
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
delete nest_card;
|
||||
nest_card = 0;
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "insert_into_postcard failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int Timestamp::retrieve_from_postcard(InPostcard * const src_card, const char * const name_str)
|
||||
{
|
||||
InPostcard * nest_card = 0;
|
||||
int result = 1;
|
||||
do
|
||||
{
|
||||
invalidate();
|
||||
|
||||
BREAK_IF_ZERO(2, name_str);
|
||||
BREAK_IF_ZERO(3, src_card);
|
||||
|
||||
BREAK_IF_NON_ZERO(10, src_card->getCard(name_str, &nest_card));
|
||||
|
||||
BREAK_IF_NON_ZERO(10, nest_card->getInt32("CLOCK_ID", m_clock_id));
|
||||
int ts_sec = 0;
|
||||
BREAK_IF_NON_ZERO(11, nest_card->getInt32("TS_SEC", ts_sec));
|
||||
m_timestamp.tv_sec = ts_sec;
|
||||
int ts_nsec = 0;
|
||||
BREAK_IF_NON_ZERO(12, nest_card->getInt32("TS_NSEC", ts_nsec));
|
||||
m_timestamp.tv_nsec = ts_nsec;
|
||||
|
||||
m_is_valid = true;
|
||||
|
||||
result = 0;
|
||||
} while (0);
|
||||
|
||||
delete nest_card;
|
||||
nest_card = 0;
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "retrieve_from_postcard failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
long long get_time_rtc_ms()
|
||||
{
|
||||
struct timeval present_time;
|
||||
long long current_time_msec;
|
||||
|
||||
// present time: seconds, and microseconds
|
||||
gettimeofday(&present_time, NULL);
|
||||
|
||||
// Calculate absolute expire time (to avoid data overflow)
|
||||
current_time_msec = present_time.tv_sec;
|
||||
current_time_msec *= 1000; // convert to milli-seconds
|
||||
|
||||
current_time_msec += (present_time.tv_usec + 500) / 1000;
|
||||
return current_time_msec;
|
||||
}
|
||||
|
||||
// Returns monotonic time
|
||||
long long get_time_monotonic_ms()
|
||||
{
|
||||
#ifndef IZAT_OFFLINE
|
||||
uint64_t current_time_msec = 0;
|
||||
struct timespec tp = {};
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
|
||||
current_time_msec = tp.tv_sec;
|
||||
current_time_msec *= 1000; // convert to milli-seconds
|
||||
|
||||
current_time_msec += ((tp.tv_nsec + 500000) / 1000000);
|
||||
return current_time_msec;
|
||||
#else
|
||||
return get_time_rtc_ms();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Check if rtc time is valid or not
|
||||
bool is_time_rtc_ms_valid(long long rtc_time_ms)
|
||||
{
|
||||
bool is_valid = false;
|
||||
|
||||
// Only if the timestamp is big enough, we consider it as valid
|
||||
if (rtc_time_ms > TIME_RTC_MS_AS_OF_12_1_2014)
|
||||
{
|
||||
is_valid = true;
|
||||
}
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
// Returns monotonic time
|
||||
long long get_time_boot_ms()
|
||||
{
|
||||
#ifdef CLOCK_BOOTTIME
|
||||
uint64_t current_time_msec = 0;
|
||||
struct timespec tp = {};
|
||||
|
||||
clock_gettime(CLOCK_BOOTTIME, &tp);
|
||||
|
||||
current_time_msec = tp.tv_sec;
|
||||
current_time_msec *= 1000; // convert to milli-seconds
|
||||
|
||||
current_time_msec += ((tp.tv_nsec + 500000) / 1000000);
|
||||
return current_time_msec;
|
||||
#else
|
||||
return get_time_rtc_ms();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
29
qcom/opensource/location/utils/base_util/string_routines.h
Normal file
29
qcom/opensource/location/utils/base_util/string_routines.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
String related routines
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This component implements portable string related routines
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef __QC_LOC_FW_STRING_H__
|
||||
#define __QC_LOC_FW_STRING_H__
|
||||
|
||||
#include <base_util/log.h>
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
#ifdef IZAT_OFFLINE
|
||||
// Android has its own strlcpy
|
||||
size_t strlcpy(char *dest, const char *src, size_t dest_capacity);
|
||||
// Android has its own strlcat
|
||||
size_t strlcat(char *dest, const char *src, size_t dest_capacity);
|
||||
#endif // #ifdef IZAT_OFFLINE
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
#endif //#ifndef __QC_LOC_FW_STRING_H__
|
||||
87
qcom/opensource/location/utils/base_util/sync.h
Normal file
87
qcom/opensource/location/utils/base_util/sync.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Sync utilities
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This header declares utilities used for thread synchronization
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#ifndef __XTRAT_WIFI_SYNC_H__
|
||||
#define __XTRAT_WIFI_SYNC_H__
|
||||
|
||||
#include <time.h>
|
||||
#include <base_util/time_routines.h>
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
class Mutex
|
||||
{
|
||||
public:
|
||||
virtual ~Mutex() = 0;
|
||||
// name is only shallow copied (only the pointer is copied), so use constant string as the name!
|
||||
static Mutex * createInstance(const char * const tag = 0, const bool verboseLog = false);
|
||||
virtual int lock() = 0;
|
||||
virtual int unlock() = 0;
|
||||
};
|
||||
|
||||
class AutoLock
|
||||
{
|
||||
private:
|
||||
Mutex * m_pMutex;
|
||||
const char * m_tag;
|
||||
bool m_locked;
|
||||
public:
|
||||
AutoLock(Mutex * const pMutex, const char * log_tag = 0);
|
||||
~AutoLock();
|
||||
int ZeroIfLocked();
|
||||
};
|
||||
|
||||
class BlockingQueue
|
||||
{
|
||||
public:
|
||||
virtual ~BlockingQueue() = 0;
|
||||
|
||||
static BlockingQueue * createInstance(const char * tag, const bool verboseLog = false);
|
||||
|
||||
virtual int push(void * const ptr) = 0;
|
||||
virtual int close() = 0;
|
||||
|
||||
// deprecated, as realtime/wall clock is not a good design choice
|
||||
// note the change in signature, that you have to explicitly specify timeout pointer to use this version
|
||||
// if you don't, you'll be using the new version with TimeDiff(false)
|
||||
virtual int pop(void ** const pptr, const timespec * const timeout_abs_realtime, bool * const p_is_queue_closed = 0) = 0;
|
||||
|
||||
// pass in TimeDiff(true) if you do not want to wait, which is valid time difference of 0
|
||||
// pass in TimeDiff(false) if you want to wait forever, which is invalid time difference
|
||||
// pass in some valid TimeDiff and we are going to wait for it
|
||||
virtual int pop(void ** const pptr, const TimeDiff & timeout = TimeDiff(false), bool * const p_is_queue_closed = 0) = 0;
|
||||
};
|
||||
|
||||
class Runnable
|
||||
{
|
||||
public:
|
||||
// expect Runnable to be deleted within Thread, and other places
|
||||
virtual ~Runnable() = 0;
|
||||
virtual void run() = 0;
|
||||
};
|
||||
|
||||
class Thread
|
||||
{
|
||||
public:
|
||||
virtual ~Thread() = 0;
|
||||
|
||||
static Thread * createInstance(const char * tag, Runnable * const pRunnable, const bool delete_runnable_at_destruction = true);
|
||||
|
||||
// call 'launch' to start execution of this thread
|
||||
virtual int launch() = 0;
|
||||
|
||||
// wait for it to complete
|
||||
virtual int join() = 0;
|
||||
};
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
#endif //#ifndef __XTRAT_WIFI_SYNC_H__
|
||||
127
qcom/opensource/location/utils/base_util/time_routines.h
Normal file
127
qcom/opensource/location/utils/base_util/time_routines.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Time related routines
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This component implements portable time related routines
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef __QC_LOC_FW_TIME_H__
|
||||
#define __QC_LOC_FW_TIME_H__
|
||||
|
||||
#include <time.h>
|
||||
#include <base_util/postcard.h>
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
class TimeDiff
|
||||
{
|
||||
public:
|
||||
// validity: false to prevent any further operation unless it's reset with true
|
||||
// or being copied/assigned with = to a valid object
|
||||
explicit TimeDiff (const bool validity = true);
|
||||
int add_sec(const int sec);
|
||||
int add_msec(const int msec);
|
||||
int add_nsec(const int nsec);
|
||||
float get_total_sec() const;
|
||||
float get_total_msec() const;
|
||||
const timespec * getTimeDiffPtr() const;
|
||||
bool is_valid() const;
|
||||
void reset(const bool validity = false);
|
||||
private:
|
||||
static const char * const TAG;
|
||||
bool m_is_valid;
|
||||
timespec m_timediff;
|
||||
};
|
||||
|
||||
class Timestamp
|
||||
{
|
||||
public:
|
||||
// set to false if you want to use reset_to_XXX functions to initialize it to
|
||||
// non-default clock, or you simply want to set it later, instead of at time of construction
|
||||
explicit Timestamp (const bool set_to_default_clock = true);
|
||||
|
||||
// use this if you want to set it to some specific clock type using clock id (defined in time.h)
|
||||
explicit Timestamp (const int clock_id);
|
||||
|
||||
// use this if you want to initialize it with pre-existing timespec acquired using some clock type
|
||||
Timestamp (const int clock_id, const timespec & src);
|
||||
|
||||
// copy constructor
|
||||
Timestamp (const Timestamp & rhs);
|
||||
|
||||
timespec * getTimestampPtr();
|
||||
const timespec * getTimestampPtr() const;
|
||||
|
||||
// use this one for most cases, which uses BOOTTIME if available, otherwise MONOTONIC
|
||||
int reset_to_default_clock();
|
||||
|
||||
// CLOCK_MONOTONIC, this might be subjected to NTP clock modulation, and might stop counting
|
||||
// when the device is sleeping
|
||||
int reset_to_monotonic();
|
||||
|
||||
// CLOCK_BOOTTIME, same as CLOCK_MONOTONIC, but should count sleeping time as well
|
||||
// currently not supported
|
||||
int reset_to_boottime();
|
||||
|
||||
// CLOCK_REALTIME. wall clock, subject to system time change. normally you don't want this
|
||||
// if you're looking for timers
|
||||
int reset_to_realtime();
|
||||
|
||||
int reset_to_clock_id(const int clock_id);
|
||||
|
||||
int get_clock_id() const;
|
||||
bool is_valid() const;
|
||||
bool is_valid_and_default() const;
|
||||
void invalidate();
|
||||
Timestamp operator + (const TimeDiff & rhs) const;
|
||||
Timestamp operator - (const TimeDiff & rhs) const;
|
||||
TimeDiff operator - (const Timestamp & rhs) const;
|
||||
bool operator >= (const Timestamp & rhs) const;
|
||||
bool operator < (const Timestamp & rhs) const;
|
||||
Timestamp & operator = (const Timestamp & rhs);
|
||||
|
||||
// timestamp is highly system-specific and doesn't translate into Java world well
|
||||
// so, please use these functions with caution
|
||||
int insert_into_postcard(OutPostcard * const dest_card, const char * const name_str);
|
||||
int retrieve_from_postcard(InPostcard * const src_card, const char * const name_str);
|
||||
private:
|
||||
static const char * const TAG;
|
||||
bool m_is_valid;
|
||||
int m_clock_id;
|
||||
timespec m_timestamp;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
// Function Name: get_time_rtc_ms
|
||||
// Description: return rtc time in milliseconds
|
||||
// represents time since the Epoch
|
||||
long long get_time_rtc_ms();
|
||||
|
||||
// Function Name: is_time_rtc_ms_valid
|
||||
// Description: Check if rtc time is valid or not
|
||||
bool is_time_rtc_ms_valid(long long rtc_time_ms);
|
||||
|
||||
// Function Name: get_time_boot_ms
|
||||
// Description: Returns monotonic time from boot
|
||||
long long get_time_boot_ms();
|
||||
|
||||
// Function Name: get_time_monotonic_ms
|
||||
// Description: Returns monotonic time
|
||||
long long get_time_monotonic_ms();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
#endif //#ifndef __QC_LOC_FW_TIME_H__
|
||||
221
qcom/opensource/location/utils/base_util/vector.h
Normal file
221
qcom/opensource/location/utils/base_util/vector.h
Normal file
@@ -0,0 +1,221 @@
|
||||
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
|
||||
|
||||
Vector template
|
||||
|
||||
GENERAL DESCRIPTION
|
||||
This component implements a vector of any type
|
||||
|
||||
Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
=============================================================================*/
|
||||
#ifndef __XTRAT_WIFI_VECTOR_H__
|
||||
#define __XTRAT_WIFI_VECTOR_H__
|
||||
|
||||
#include <base_util/log.h>
|
||||
|
||||
namespace qc_loc_fw
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
class vector
|
||||
{
|
||||
private:
|
||||
static const char * const TAG;
|
||||
static const int DEFAULT_CAPACITY = 64;
|
||||
public:
|
||||
|
||||
typedef T * Iterator;
|
||||
|
||||
vector() :
|
||||
m_pArray(0), m_capacity(0), m_num_elements(0)
|
||||
{
|
||||
}
|
||||
|
||||
vector(const vector<T> & rhs) :
|
||||
m_pArray(0), m_capacity(0), m_num_elements(0)
|
||||
{
|
||||
(void) operator =(rhs);
|
||||
}
|
||||
|
||||
virtual ~vector()
|
||||
{
|
||||
flush();
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
if(0 != m_pArray)
|
||||
{
|
||||
delete[] m_pArray;
|
||||
m_pArray = 0;
|
||||
}
|
||||
m_capacity = 0;
|
||||
m_num_elements = 0;
|
||||
}
|
||||
|
||||
int push_back(const T & element)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
// Check if the Array has been allocated already.
|
||||
if (0 == m_pArray)
|
||||
{
|
||||
// Inserting an element where as the Array is not yet allocated
|
||||
// Allocate the array to default size
|
||||
m_capacity = DEFAULT_CAPACITY;
|
||||
m_pArray = new (std::nothrow) T[m_capacity];
|
||||
if (0 == m_pArray)
|
||||
{
|
||||
result = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Memory is already allocated. Check if the Array is running on boundary
|
||||
if (m_capacity == m_num_elements)
|
||||
{
|
||||
// We do not have space for more elements
|
||||
// Double the size and copy over the elements in new array
|
||||
unsigned int new_size = 2 * m_capacity;
|
||||
T* pNewArray = new (std::nothrow) T[new_size];
|
||||
if (0 != pNewArray)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_capacity; ++i)
|
||||
{
|
||||
pNewArray[i] = m_pArray[i];
|
||||
}
|
||||
m_capacity = new_size;
|
||||
delete [] m_pArray;
|
||||
m_pArray = pNewArray;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == result)
|
||||
{
|
||||
// Store the new element
|
||||
m_pArray [m_num_elements] = element;
|
||||
++m_num_elements;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "insertion failed %d", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
T & operator [](const unsigned int index)
|
||||
{
|
||||
if(index < m_num_elements)
|
||||
{
|
||||
return m_pArray[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "index out of range\n");
|
||||
// could be null reference, but we're doomed anyway
|
||||
return m_pArray[0];
|
||||
}
|
||||
}
|
||||
|
||||
const T & operator [](const unsigned int index) const
|
||||
{
|
||||
if(index < m_num_elements)
|
||||
{
|
||||
return m_pArray[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(TAG, "index out of range\n");
|
||||
// could be null reference, but we're doomed anyway
|
||||
return m_pArray[0];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int getNumOfElements() const
|
||||
{
|
||||
return m_num_elements;
|
||||
}
|
||||
|
||||
unsigned int getCapacity() const
|
||||
{
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
const vector<T> & operator =(const vector<T> & rhs)
|
||||
{
|
||||
int result = 1;
|
||||
|
||||
if(&rhs == this)
|
||||
{
|
||||
// do nothing for self-assignment
|
||||
return *this;
|
||||
}
|
||||
|
||||
flush();
|
||||
int new_size = rhs.getCapacity();
|
||||
|
||||
if(new_size > 0)
|
||||
{
|
||||
int elements = rhs.getNumOfElements();
|
||||
T * pNewArray = new (std::nothrow) T[new_size];
|
||||
if(0 != pNewArray)
|
||||
{
|
||||
for (int i = 0; i < elements; ++i)
|
||||
{
|
||||
pNewArray[i] = rhs.m_pArray[i];
|
||||
}
|
||||
m_capacity = new_size;
|
||||
m_num_elements = elements;
|
||||
|
||||
if(0 != m_pArray)
|
||||
{
|
||||
delete[] m_pArray;
|
||||
}
|
||||
m_pArray = pNewArray;
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing. it's okay to insert empty array into an array
|
||||
result = 0;
|
||||
}
|
||||
|
||||
if(0 != result)
|
||||
{
|
||||
log_error(TAG, "assignment failed %d", result);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator begin()
|
||||
{
|
||||
return Iterator(m_pArray);
|
||||
}
|
||||
|
||||
Iterator end()
|
||||
{
|
||||
return Iterator(m_pArray + m_num_elements);
|
||||
}
|
||||
|
||||
private:
|
||||
T * m_pArray;
|
||||
unsigned int m_capacity;
|
||||
unsigned int m_num_elements;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
const char * const vector<T>::TAG = "vector";
|
||||
|
||||
} // namespace qc_loc_fw
|
||||
|
||||
#endif //#ifndef __XTRAT_WIFI_VECTOR_H__
|
||||
37
qcom/opensource/location/utils/loc_socket/Android.mk
Normal file
37
qcom/opensource/location/utils/loc_socket/Android.mk
Normal file
@@ -0,0 +1,37 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := libloc_socket
|
||||
LOCAL_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/lib
|
||||
LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libutils \
|
||||
libcutils \
|
||||
liblog \
|
||||
libgps.utils
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
LocSocket.cpp
|
||||
|
||||
LOCAL_CFLAGS := \
|
||||
-fno-short-enums \
|
||||
-D_ANDROID_
|
||||
|
||||
LOCAL_HEADER_LIBRARIES := \
|
||||
libqmi_common_headers \
|
||||
libloc_core_headers \
|
||||
libgps.utils_headers \
|
||||
libloc_pla_headers \
|
||||
liblocation_api_headers
|
||||
LOCAL_CFLAGS += $(GNSS_CFLAGS)
|
||||
|
||||
ifeq ($(TARGET_KERNEL_VERSION),$(filter $(TARGET_KERNEL_VERSION),3.18 4.4 4.9))
|
||||
LOCAL_CFLAGS += -DUSE_QSOCKET
|
||||
LOCAL_HEADER_LIBRARIES += libqsocket_headers
|
||||
LOCAL_SHARED_LIBRARIES += libqsocket
|
||||
endif
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
456
qcom/opensource/location/utils/loc_socket/LocSocket.cpp
Normal file
456
qcom/opensource/location/utils/loc_socket/LocSocket.cpp
Normal file
@@ -0,0 +1,456 @@
|
||||
/* Copyright (c) 2019 - 2021 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.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from Qualcomm Innovation Center are provided under the following license:
|
||||
|
||||
Copyright (c) 2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted (subject to the limitations in the
|
||||
disclaimer below) 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 Qualcomm Innovation Center, Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
|
||||
GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
|
||||
HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <unistd.h>
|
||||
#include <memory>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef USE_QSOCKET
|
||||
#include <sys/ioctl.h>
|
||||
#include <poll.h>
|
||||
#include <qsocket.h>
|
||||
#include <qsocket_ipcr.h>
|
||||
#else
|
||||
#include <endian.h>
|
||||
#include <linux/qrtr.h>
|
||||
#endif
|
||||
|
||||
#include <log_util.h>
|
||||
#include <LocIpc.h>
|
||||
|
||||
namespace loc_util {
|
||||
|
||||
#ifdef LOG_TAG
|
||||
#undef LOG_TAG
|
||||
#endif
|
||||
#define LOG_TAG "LocSvc_Qrtr"
|
||||
|
||||
class ServiceInfo {
|
||||
const int32_t mServiceId;
|
||||
const int32_t mInstanceId;
|
||||
const string mName;
|
||||
public:
|
||||
inline ServiceInfo(int32_t service, int32_t instance) :
|
||||
mServiceId(service), mInstanceId(instance),
|
||||
mName(to_string(service) + ":" + to_string(instance)) {}
|
||||
inline const char* getName() const { return mName.data(); }
|
||||
inline int32_t getServiceId() const { return mServiceId; }
|
||||
inline int32_t getInstanceId() const { return mInstanceId; }
|
||||
};
|
||||
|
||||
#ifdef USE_QSOCKET
|
||||
|
||||
class LocIpcQsockSender : public LocIpcSender {
|
||||
protected:
|
||||
shared_ptr<Sock> mSock;
|
||||
const ServiceInfo mServiceInfo;
|
||||
qsockaddr_ipcr mAddr;
|
||||
mutable bool mLookupPending;
|
||||
inline virtual bool isOperable() const override {
|
||||
return mSock != nullptr && mSock->mSid != -1;
|
||||
}
|
||||
inline void serviceLookup() const {
|
||||
if (mLookupPending && mSock->isValid()) {
|
||||
ipcr_name_t ipcrName = {
|
||||
.service = (uint32_t)mServiceInfo.getServiceId(),
|
||||
.instance = (uint32_t)mServiceInfo.getInstanceId()
|
||||
};
|
||||
uint32_t numEntries = 1;
|
||||
int rc = ipcr_find_name(mSock->mSid, &ipcrName,
|
||||
(struct qsockaddr_ipcr*)&mAddr, NULL, &numEntries, 0);
|
||||
LOC_LOGd("serviceLookup, rc = %d, numEntries = %d\n", rc, numEntries);
|
||||
if (rc < 0 || 1 != numEntries) {
|
||||
mSock->close();
|
||||
}
|
||||
mLookupPending = false;
|
||||
}
|
||||
}
|
||||
inline virtual ssize_t send(const uint8_t data[], uint32_t length,
|
||||
int32_t /* msgId */) const override {
|
||||
serviceLookup();
|
||||
return mSock->send(data, length, 0, (struct sockaddr*)&mAddr,
|
||||
sizeof(mAddr));
|
||||
}
|
||||
public:
|
||||
inline LocIpcQsockSender(const qsockaddr_ipcr& destAddr) :
|
||||
LocIpcSender(),
|
||||
mSock(make_shared<Sock>(::socket(AF_IPC_ROUTER, SOCK_DGRAM, 0))),
|
||||
mServiceInfo(0, 0), mAddr(destAddr), mLookupPending(false) {
|
||||
}
|
||||
|
||||
inline LocIpcQsockSender(int service, int instance) :
|
||||
LocIpcSender(),
|
||||
mSock(make_shared<Sock>(::socket(AF_IPC_ROUTER, SOCK_DGRAM, 0))),
|
||||
mServiceInfo(service, instance), mAddr({}), mLookupPending(true) {
|
||||
}
|
||||
|
||||
unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener) override {
|
||||
return make_unique<SockRecver>(listener, *this, mSock);
|
||||
}
|
||||
};
|
||||
|
||||
class LocIpcQsockRecver : public LocIpcQsockSender, public LocIpcRecver {
|
||||
protected:
|
||||
inline virtual ssize_t recv() const override {
|
||||
socklen_t size = sizeof(mAddr);
|
||||
return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size);
|
||||
}
|
||||
public:
|
||||
inline LocIpcQsockRecver(const shared_ptr<ILocIpcListener>& listener,
|
||||
int service, int instance) :
|
||||
LocIpcQsockSender(service, instance),
|
||||
LocIpcRecver(listener, *this) {
|
||||
qsockaddr_ipcr addr = {
|
||||
AF_IPC_ROUTER,
|
||||
{
|
||||
IPCR_ADDR_NAME,
|
||||
{
|
||||
(uint32_t)service,
|
||||
(uint32_t)instance
|
||||
}
|
||||
},
|
||||
0
|
||||
};
|
||||
if (mSock->isValid() &&
|
||||
::bind(mSock->mSid, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
|
||||
LOC_LOGe("bind socket error. sock fd: %d,reason: %s",
|
||||
mSock->mSid, strerror(errno));
|
||||
mSock->close();
|
||||
}
|
||||
}
|
||||
inline virtual unique_ptr<LocIpcSender> getLastSender() const override {
|
||||
return make_unique<LocIpcQsockSender>(mAddr);
|
||||
}
|
||||
inline virtual const char* getName() const override {
|
||||
return mServiceInfo.getName();
|
||||
}
|
||||
inline virtual void abort() const override {
|
||||
if (isSendable()) {
|
||||
serviceLookup();
|
||||
mSock->sendAbort(0, (struct sockaddr*)&mAddr, sizeof(mAddr));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
shared_ptr<LocIpcSender> createLocIpcQrtrSender(int service, int instance) {
|
||||
return make_shared<LocIpcQsockSender>(service, instance);
|
||||
}
|
||||
unique_ptr<LocIpcRecver> createLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
|
||||
int service, int instance,
|
||||
const shared_ptr<LocIpcQrtrWatcher>& qrtrWatcher) {
|
||||
return make_unique<LocIpcQsockRecver>(listener, service, instance);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define SOCKET_SENDER_SEND_TIMEOUT_MSEC 100
|
||||
|
||||
static inline __le32 cpu_to_le32(uint32_t x) { return htole32(x); }
|
||||
static inline uint32_t le32_to_cpu(__le32 x) { return le32toh(x); }
|
||||
|
||||
class LocIpcQrtrSender : public LocIpcSender {
|
||||
protected:
|
||||
const ServiceInfo mServiceInfo;
|
||||
shared_ptr<Sock> mSock;
|
||||
mutable sockaddr_qrtr mAddr;
|
||||
mutable sockaddr_qrtr mCtrlPntAddr;
|
||||
mutable struct qrtr_ctrl_pkt mCtrlPkt;
|
||||
mutable bool mLookupPending;
|
||||
bool ctrlCmdAndResponse(enum qrtr_pkt_type cmd) const {
|
||||
LOC_LOGd("cmd: %d, sock valid %d, sock id %d, service id %d, instance id %d",
|
||||
cmd, mSock->isValid(), mSock->mSid,
|
||||
le32_to_cpu(mCtrlPkt.server.service),
|
||||
le32_to_cpu(mCtrlPkt.server.instance));
|
||||
if (mSock->isValid()) {
|
||||
int rc = 0;
|
||||
mCtrlPkt.cmd = cpu_to_le32(cmd);
|
||||
if ((rc = ::sendto(mSock->mSid, &mCtrlPkt, sizeof(mCtrlPkt), 0,
|
||||
(const struct sockaddr *)&mCtrlPntAddr, sizeof(mCtrlPntAddr))) < 0) {
|
||||
LOC_LOGe("failed: sendto rc=%d reason=(%s)", rc, strerror(errno));
|
||||
} else if (QRTR_TYPE_NEW_LOOKUP == cmd) {
|
||||
int len = 0;
|
||||
struct qrtr_ctrl_pkt pkt;
|
||||
while ((len = ::recv(mSock->mSid, &pkt, sizeof(pkt), 0)) > 0) {
|
||||
if (len >= (decltype(len))sizeof(pkt)) {
|
||||
qrtr_pkt_type pktType = (qrtr_pkt_type) le32_to_cpu(pkt.cmd);
|
||||
LOC_LOGd("qrtr new lookup received pkt type: %d, "
|
||||
"pkt service id: %d, instance id: %d,"
|
||||
"node %d, port %d",
|
||||
pktType, le32_to_cpu(pkt.server.service),
|
||||
le32_to_cpu(pkt.server.instance),
|
||||
le32_to_cpu(pkt.server.node),
|
||||
le32_to_cpu(pkt.server.port));
|
||||
|
||||
switch (pktType){
|
||||
case QRTR_TYPE_NEW_SERVER:
|
||||
if (le32_to_cpu(pkt.server.service) == 0 &&
|
||||
le32_to_cpu(pkt.server.instance) == 0) {
|
||||
return false;
|
||||
} else if ((mCtrlPkt.server.service == pkt.server.service) &&
|
||||
(mCtrlPkt.server.instance == pkt.server.instance)) {
|
||||
mAddr.sq_node = le32_to_cpu(pkt.server.node);
|
||||
mAddr.sq_port = le32_to_cpu(pkt.server.port);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case QRTR_TYPE_DEL_SERVER:
|
||||
if ((mCtrlPkt.server.service == pkt.server.service) &&
|
||||
(mCtrlPkt.server.instance == pkt.server.instance)) {
|
||||
// service of particular service id, instance id gets deleted
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LOC_LOGd("cmd: %d, return %d", cmd, mSock->isValid());
|
||||
return mSock->isValid();
|
||||
}
|
||||
|
||||
inline virtual bool isOperable() const override {
|
||||
return mSock != nullptr && mSock->isValid() &&
|
||||
(mAddr.sq_node != 0 || mAddr.sq_port != 0);
|
||||
}
|
||||
|
||||
inline virtual ssize_t send(const uint8_t data[], uint32_t length,
|
||||
int32_t /* msgId */) const override {
|
||||
if (mLookupPending) {
|
||||
if (ctrlCmdAndResponse(QRTR_TYPE_NEW_LOOKUP) == false) {
|
||||
return 0;
|
||||
}
|
||||
mLookupPending = false;
|
||||
}
|
||||
int result = mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
|
||||
return result;
|
||||
}
|
||||
public:
|
||||
inline LocIpcQrtrSender(const sockaddr_qrtr& destAddr) :
|
||||
LocIpcSender(), mServiceInfo(0, 0),
|
||||
mSock(make_shared<Sock>(::socket(AF_QIPCRTR, SOCK_DGRAM, 0))),
|
||||
mAddr(destAddr), mCtrlPkt({}), mLookupPending(false) {
|
||||
}
|
||||
inline LocIpcQrtrSender(int service, int instance) : LocIpcSender(),
|
||||
mServiceInfo(service, instance),
|
||||
mSock(make_shared<Sock>(::socket(AF_QIPCRTR, SOCK_DGRAM, 0))),
|
||||
mAddr({AF_QIPCRTR, 0, 0}),
|
||||
mCtrlPkt({}),
|
||||
mLookupPending(true) {
|
||||
// set timeout so if failed to send, call will return after SOCKET_TIMEOUT_MSEC
|
||||
// otherwise, call may never return
|
||||
timeval timeout;
|
||||
|
||||
timeout.tv_sec = SOCKET_SENDER_SEND_TIMEOUT_MSEC / 1000;
|
||||
timeout.tv_usec = SOCKET_SENDER_SEND_TIMEOUT_MSEC % 1000 * 1000;
|
||||
setsockopt(mSock->mSid, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
||||
|
||||
socklen_t sl = sizeof(mAddr);
|
||||
int rc = 0;
|
||||
if ((rc = getsockname(mSock->mSid, (struct sockaddr*)&mAddr, &sl)) ||
|
||||
mAddr.sq_family != AF_QIPCRTR || sl != sizeof(mAddr)) {
|
||||
LOC_LOGe("failed: getsockname rc=%d reason=(%s), mAddr.sq_family=%d",
|
||||
rc, strerror(errno), mAddr.sq_family);
|
||||
mSock->close();
|
||||
} else {
|
||||
mCtrlPkt.server.service = cpu_to_le32(service);
|
||||
mCtrlPkt.server.instance = cpu_to_le32(instance);
|
||||
mCtrlPkt.server.node = cpu_to_le32(mAddr.sq_node);
|
||||
mCtrlPkt.server.port = cpu_to_le32(mAddr.sq_port);
|
||||
mCtrlPntAddr = mAddr;
|
||||
mCtrlPntAddr.sq_port = QRTR_PORT_CTRL;
|
||||
}
|
||||
}
|
||||
|
||||
unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener) override {
|
||||
return make_unique<SockRecver>(listener, *this, mSock);
|
||||
}
|
||||
|
||||
inline virtual bool updateDestAddr(uint32_t nodeId, uint32_t portId)
|
||||
{
|
||||
if (mAddr.sq_node != nodeId || mAddr.sq_port != portId) {
|
||||
sockaddr_qrtr addr = {AF_QIPCRTR, nodeId, portId};
|
||||
mAddr = addr;
|
||||
}
|
||||
mLookupPending = false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class LocIpcQrtrListener : public ILocIpcListener {
|
||||
const shared_ptr<ILocIpcListener> mRealListener;
|
||||
const shared_ptr<LocIpcQrtrWatcher> mQrtrWatcher;
|
||||
inline bool handleQrtrCtrlMsg(const char* data, uint32_t len) {
|
||||
const struct qrtr_ctrl_pkt* pkt = reinterpret_cast<const struct qrtr_ctrl_pkt*>(data);
|
||||
bool handledAsQrtrCtrlMsg = false;
|
||||
|
||||
if (sizeof(*pkt) == len) {
|
||||
const uint32_t cmd = le32_to_cpu(pkt->cmd);
|
||||
if (cmd >= QRTR_TYPE_DATA && cmd <= QRTR_TYPE_DEL_LOOKUP) {
|
||||
handledAsQrtrCtrlMsg = true;
|
||||
int serviceId = le32_to_cpu(pkt->server.service);
|
||||
int instanceId = le32_to_cpu(pkt->server.instance);
|
||||
uint32_t serverNodeId = le32_to_cpu(pkt->server.node);
|
||||
uint32_t serverPort = le32_to_cpu(pkt->server.port);
|
||||
int clientNodeId = le32_to_cpu(pkt->client.node);
|
||||
int clientPort = le32_to_cpu(pkt->client.port);
|
||||
|
||||
LOC_LOGv("qrtr control msg: cmd %d, server.service:instance-node:port %d:%d-%d:%d,"
|
||||
" client node:port %d:%d", cmd, serviceId, instanceId, serverNodeId,
|
||||
serverPort, clientNodeId, clientPort);
|
||||
|
||||
if (nullptr != mQrtrWatcher) {
|
||||
if ((QRTR_TYPE_NEW_SERVER == cmd || QRTR_TYPE_DEL_SERVER == cmd) &&
|
||||
mQrtrWatcher->isServiceInWatch(serviceId)) {
|
||||
LocIpcQrtrWatcher::ServiceStatus status = (QRTR_TYPE_NEW_SERVER == cmd) ?
|
||||
LocIpcQrtrWatcher::ServiceStatus::UP :
|
||||
LocIpcQrtrWatcher::ServiceStatus::DOWN;
|
||||
mQrtrWatcher->onServiceStatusChange(serviceId, instanceId, status,
|
||||
serverNodeId, serverPort);
|
||||
} else if ((QRTR_TYPE_DEL_CLIENT == cmd || QRTR_TYPE_BYE == cmd) &&
|
||||
mQrtrWatcher->isClientInWatch(clientNodeId)) {
|
||||
mQrtrWatcher->onClientGone(clientNodeId, clientPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return handledAsQrtrCtrlMsg;
|
||||
}
|
||||
public:
|
||||
inline LocIpcQrtrListener(const shared_ptr<ILocIpcListener>& listener,
|
||||
const shared_ptr<LocIpcQrtrWatcher>& qrtrWatcher) :
|
||||
mRealListener(listener), mQrtrWatcher(qrtrWatcher) {}
|
||||
inline virtual void onListenerReady() override {
|
||||
if (nullptr != mRealListener) mRealListener->onListenerReady();
|
||||
}
|
||||
inline virtual void onReceive(const char* data, uint32_t len,
|
||||
const LocIpcRecver* recver) override {
|
||||
if ((!handleQrtrCtrlMsg(data, len)) && (nullptr != mRealListener)) {
|
||||
mRealListener->onReceive(data, len, recver);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class LocIpcQrtrRecver : public LocIpcQrtrSender, public LocIpcRecver {
|
||||
protected:
|
||||
inline virtual ssize_t recv() const override {
|
||||
socklen_t size = sizeof(mAddr);
|
||||
return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size);
|
||||
}
|
||||
public:
|
||||
inline LocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
|
||||
int service, int instance,
|
||||
const shared_ptr<LocIpcQrtrWatcher>& qrtrWatcher) :
|
||||
LocIpcQrtrSender(service, instance),
|
||||
LocIpcRecver(make_shared<LocIpcQrtrListener>(listener, qrtrWatcher), *this) {
|
||||
|
||||
ctrlCmdAndResponse(QRTR_TYPE_NEW_SERVER);
|
||||
|
||||
if (nullptr != qrtrWatcher) {
|
||||
struct qrtr_ctrl_pkt pkt = {};
|
||||
pkt.cmd = cpu_to_le32(QRTR_TYPE_NEW_LOOKUP);
|
||||
int rc = 0;
|
||||
for (int serviceId : qrtrWatcher->getServicesToWatch()) {
|
||||
pkt.server.service = cpu_to_le32(serviceId);
|
||||
LOC_LOGd("watch for service: %d", pkt.server.service);
|
||||
if ((rc = ::sendto(mSock->mSid, &pkt, sizeof(pkt), 0,
|
||||
(const struct sockaddr *)&mCtrlPntAddr,
|
||||
sizeof(mCtrlPntAddr))) < 0) {
|
||||
LOC_LOGe("failed: sendto rc=%d reason=(%s)\n", rc, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline ~LocIpcQrtrRecver() { ctrlCmdAndResponse(QRTR_TYPE_DEL_SERVER); }
|
||||
inline virtual unique_ptr<LocIpcSender> getLastSender() const override {
|
||||
return make_unique<LocIpcQrtrSender>(mAddr);
|
||||
}
|
||||
inline virtual const char* getName() const override {
|
||||
return mServiceInfo.getName();
|
||||
}
|
||||
inline virtual void abort() const override {
|
||||
if (isSendable()) {
|
||||
mSock->sendAbort(0, (struct sockaddr*)&mAddr, sizeof(mAddr));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
shared_ptr<LocIpcSender> createLocIpcQrtrSender(int service, int instance) {
|
||||
return make_shared<LocIpcQrtrSender>(service, instance);
|
||||
}
|
||||
unique_ptr<LocIpcRecver> createLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
|
||||
int service, int instance,
|
||||
const shared_ptr<LocIpcQrtrWatcher>& qrtrWatcher) {
|
||||
return make_unique<LocIpcQrtrRecver>(listener, service, instance, qrtrWatcher);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
50
qcom/opensource/location/utils/loc_socket/Makefile.am
Normal file
50
qcom/opensource/location/utils/loc_socket/Makefile.am
Normal file
@@ -0,0 +1,50 @@
|
||||
AM_CFLAGS = \
|
||||
-DDEBUG \
|
||||
-I src/ \
|
||||
-I inc/ \
|
||||
$(QMIFW_CFLAGS) \
|
||||
$(GPSUTILS_CFLAGS) \
|
||||
-fpermissive
|
||||
|
||||
if USE_QSOCKET
|
||||
AM_CFLAGS += -DUSE_QSOCKET
|
||||
endif
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
AM_CPPFLAGS = -std=c++14
|
||||
|
||||
requiredlibs = \
|
||||
$(QMIFW_LIBS) \
|
||||
$(GPSUTILS_LIBS)
|
||||
|
||||
c_sources = \
|
||||
LocSocket.cpp
|
||||
|
||||
libloc_socket_la_SOURCES = \
|
||||
$(c_sources)
|
||||
|
||||
######################
|
||||
# Build loc_socket
|
||||
######################
|
||||
|
||||
if USE_GLIB
|
||||
libloc_socket_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@
|
||||
libloc_socket_la_LDFLAGS = -lstdc++ -g -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0
|
||||
libloc_socket_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@
|
||||
else
|
||||
libloc_socket_la_CFLAGS = $(AM_CFLAGS)
|
||||
libloc_socket_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread -shared -version-info 1:0:0
|
||||
libloc_socket_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
|
||||
endif
|
||||
|
||||
libloc_socket_la_LIBADD = $(requiredlibs) -lstdc++
|
||||
|
||||
#Create and Install libraries
|
||||
library_include_HEADERS =
|
||||
lib_LTLIBRARIES = libloc_socket.la
|
||||
|
||||
library_includedir = $(pkgincludedir)
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = loc-socket.pc
|
||||
EXTRA_DIST = $(pkgconfig_DATA)
|
||||
|
||||
117
qcom/opensource/location/utils/loc_socket/configure.ac
Normal file
117
qcom/opensource/location/utils/loc_socket/configure.ac
Normal file
@@ -0,0 +1,117 @@
|
||||
# configure.ac -- Autoconf script for gps location-utils
|
||||
#
|
||||
# Process this file with autoconf to produce a configure script
|
||||
|
||||
# Requires autoconf tool later than 2.61
|
||||
AC_PREREQ(2.61)
|
||||
# Initialize the loc_socket package version 1.0.0
|
||||
AC_INIT([loc-socket],1.0.0)
|
||||
# Does not strictly follow GNU Coding standards
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||
# Disables auto rebuilding of configure, Makefile.ins
|
||||
AM_MAINTAINER_MODE
|
||||
# Verifies the --srcdir is correct by checking for the path
|
||||
AC_CONFIG_SRCDIR([Makefile.am])
|
||||
# defines some macros variable to be included by source
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_LIBTOOL
|
||||
AC_PROG_CXX
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_AWK
|
||||
AC_PROG_CPP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
# Checks for libraries.
|
||||
PKG_CHECK_MODULES([GPSUTILS], [qcom-gps-utils])
|
||||
AC_SUBST([GPSUTILS_CFLAGS])
|
||||
AC_SUBST([GPSUTILS_LIBS])
|
||||
|
||||
AC_ARG_WITH([external_ap],
|
||||
AC_HELP_STRING([--with-external_ap=@<:@dir@:>@],
|
||||
[Using External Application Processor]),
|
||||
[],
|
||||
with_external_ap=no)
|
||||
|
||||
if test "x$with_external_ap" != "xno"; then
|
||||
CPPFLAGS="${CPPFLAGS} -DFEATURE_EXTERNAL_AP"
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(USE_EXTERNAL_AP, test "x${with_external_ap}" = "xyes")
|
||||
|
||||
AC_ARG_WITH([qsocket],
|
||||
AC_HELP_STRING([--with-qsocket], [kernel supports qsocket]))
|
||||
|
||||
AM_CONDITIONAL(USE_QSOCKET, test "x${with_qsocket}" = "xyes")
|
||||
AM_COND_IF(USE_QSOCKET, [
|
||||
PKG_CHECK_MODULES([QMIFW], [qmi-framework])
|
||||
AC_SUBST([QMIFW_CFLAGS])
|
||||
AC_SUBST([QMIFW_LIBS])
|
||||
])
|
||||
|
||||
AC_ARG_WITH([external_ap],
|
||||
AC_HELP_STRING([--with-external_ap=@<:@dir@:>@],
|
||||
[Using External Application Processor]),
|
||||
[],
|
||||
with_external_ap=no)
|
||||
|
||||
if test "x$with_external_ap" != "xno"; then
|
||||
CPPFLAGS="${CPPFLAGS} -DFEATURE_EXTERNAL_AP"
|
||||
else
|
||||
# Checks for libraries.
|
||||
PKG_CHECK_MODULES([CUTILS], [libcutils])
|
||||
AC_SUBST([CUTILS_CFLAGS])
|
||||
AC_SUBST([CUTILS_LIBS])
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([glib],
|
||||
AC_HELP_STRING([--with-glib],
|
||||
[enable glib, building HLOS systems which use glib]))
|
||||
|
||||
if (test "x${with_glib}" = "xyes"); then
|
||||
AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib])
|
||||
PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes,
|
||||
AC_MSG_ERROR(GThread >= 2.16 is required))
|
||||
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
|
||||
AC_MSG_ERROR(GLib >= 2.16 is required))
|
||||
GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
|
||||
GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
|
||||
|
||||
AC_SUBST(GLIB_CFLAGS)
|
||||
AC_SUBST(GLIB_LIBS)
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
|
||||
|
||||
AC_ARG_WITH([core_includes],
|
||||
AC_HELP_STRING([--with-core-includes=@<:@dir@:>@],
|
||||
[Specify the location of the core headers]),
|
||||
[core_incdir=$withval],
|
||||
with_core_includes=no)
|
||||
|
||||
if test "x$with_core_includes" != "xno"; then
|
||||
CPPFLAGS="${CPPFLAGS} -I${core_incdir}"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([locpla_includes],
|
||||
AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@],
|
||||
[specify the path to locpla-includes in loc-pla_git.bb]),
|
||||
[locpla_incdir=$withval],
|
||||
with_locpla_includes=no)
|
||||
|
||||
if test "x$with_locpla_includes" != "xno"; then
|
||||
AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}")
|
||||
fi
|
||||
|
||||
AC_CONFIG_FILES([ \
|
||||
Makefile \
|
||||
loc-socket.pc
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
10
qcom/opensource/location/utils/loc_socket/loc-socket.pc.in
Normal file
10
qcom/opensource/location/utils/loc_socket/loc-socket.pc.in
Normal file
@@ -0,0 +1,10 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: loc-socket
|
||||
Description: location socket library
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lloc_socket
|
||||
Cflags: -I${includedir} -I${includedir}/loc-socket
|
||||
Reference in New Issue
Block a user