sm8250-common: import gps from LA.UM.9.12.r1-13500.01-SMxx50.QSSI12.0

Change-Id: Ib5a80c095e5e203f90cc0d685758553fd18a7f0c
This commit is contained in:
SGCMarkus 2022-03-23 21:36:50 +01:00
parent e4e7e5be57
commit 72410cf795
270 changed files with 66183 additions and 615 deletions

54
gps/utils/Android.bp Normal file
View file

@ -0,0 +1,54 @@
cc_library_shared {
name: "libgps.utils",
vendor: true,
//# Libs
shared_libs: [
"libdl",
"libutils",
"libcutils",
"liblog",
"libprocessgroup",
],
srcs: [
"loc_log.cpp",
"loc_cfg.cpp",
"msg_q.c",
"linked_list.c",
"loc_target.cpp",
"LocHeap.cpp",
"LocTimer.cpp",
"LocThread.cpp",
"MsgTask.cpp",
"loc_misc_utils.cpp",
"loc_nmea.cpp",
"LocIpc.cpp",
"LogBuffer.cpp",
],
cflags: [
"-fno-short-enums",
"-D_ANDROID_",
] + GNSS_CFLAGS,
//# Includes
ldflags: ["-Wl,--export-dynamic"],
header_libs: [
"libutils_headers",
"libloc_pla_headers",
"liblocation_api_headers",
],
}
cc_library_headers {
name: "libgps.utils_headers",
export_include_dirs: ["."],
vendor: true,
}

280
gps/utils/LocHeap.cpp Normal file
View file

@ -0,0 +1,280 @@
/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <LocHeap.h>
namespace loc_util {
class LocHeapNode {
friend class LocHeap;
// size of of the subtree, excluding self, 1 if no subtree
int mSize;
LocHeapNode* mLeft;
LocHeapNode* mRight;
LocRankable* mData;
public:
inline LocHeapNode(LocRankable& data) :
mSize(1), mLeft(NULL), mRight(NULL), mData(&data) {}
~LocHeapNode();
// this only swaps the data of the two nodes, so no
// detach / re-attached is necessary
void swap(LocHeapNode& node);
LocRankable* detachData();
// push a node into the tree stucture, keeping sorted by rank
void push(LocHeapNode& node);
// pop the head node out of the tree stucture. keeping sorted by rank
static LocHeapNode* pop(LocHeapNode*& top);
// remove a specific node from the tree
// returns the pointer to the node removed, which would be either the
// same as input (if successfully removed); or NULL (if failed).
static LocHeapNode* remove(LocHeapNode*& top, LocRankable& data);
// convenience method to compare data ranking
inline bool outRanks(LocHeapNode& node) { return mData->outRanks(*node.mData); }
inline bool outRanks(LocRankable& data) { return mData->outRanks(data); }
// checks if mSize is correct, AND this node is the highest ranking
// of the entire subtree
bool checkNodes();
inline int getSize() { return mSize; }
};
inline
LocHeapNode::~LocHeapNode() {
if (mLeft) {
delete mLeft;
mLeft = NULL;
}
if (mRight) {
delete mRight;
mRight = NULL;
}
if (mData) {
mData = NULL;
}
}
inline
void LocHeapNode::swap(LocHeapNode& node) {
LocRankable* tmpData = node.mData;
node.mData = mData;
mData = tmpData;
}
inline
LocRankable* LocHeapNode::detachData() {
LocRankable* data = mData;
mData = NULL;
return data;
}
// push keeps the tree sorted by rank, it also tries to balance the
// tree by adding the new node to the smaller of the subtrees.
// The pointer to the tree and internal links never change. If the
// mData of tree top ranks lower than that of the incoming node,
// mData will be swapped with that of the incoming node to ensure
// ranking, no restructuring the container nodes.
void LocHeapNode::push(LocHeapNode& node) {
// ensure the current node ranks higher than in the incoming one
if (node.outRanks(*this)) {
swap(node);
}
// now drop the new node (ensured lower than *this) into a subtree
if (NULL == mLeft) {
mLeft = &node;
} else if (NULL == mRight) {
mRight = &node;
} else if (mLeft->mSize <= mRight->mSize) {
mLeft->push(node);
} else {
mRight->push(node);
}
mSize++;
}
// pop keeps the tree sorted by rank, but it does not try to balance
// the tree. It recursively swaps with the higher ranked top of the
// subtrees.
// The return is a popped out node from leaf level, that has the data
// swapped all the way down from the top. The pinter to the tree and
// internal links will not be changed or restructured, except for the
// node that is popped out.
// If the return pointer == this, this the last node in the tree.
LocHeapNode* LocHeapNode::pop(LocHeapNode*& top) {
// we know the top has the highest ranking at this point, else
// the tree is broken. This top will be popped out. But we need
// a node from the left or right child, whichever ranks higher,
// to replace the current top. This then will need to be done
// recursively to the leaf level. So we swap the mData of the
// current top node all the way down to the leaf level.
LocHeapNode* poppedNode = top;
// top is losing a node in its subtree
top->mSize--;
if (top->mLeft || top->mRight) {
// if mLeft is NULL, mRight for sure is NOT NULL, take that;
// else if mRight is NULL, mLeft for sure is NOT, take that;
// else we take the address of whatever has higher ranking mData
LocHeapNode*& subTop = (NULL == top->mLeft) ? top->mRight :
((NULL == top->mRight) ? top->mLeft :
(top->mLeft->outRanks(*(top->mRight)) ? top->mLeft : top->mRight));
// swap mData, the tree top gets updated with the new data.
top->swap(*subTop);
// pop out from the subtree
poppedNode = pop(subTop);
} else {
// if the top has only single node
// detach the poppedNode from the tree
// subTop is the reference of ether mLeft or mRight
// NOT a local stack pointer. so it MUST be NULL'ed here.
top = NULL;
}
return poppedNode;
}
// navigating through the tree and find the node that hass the input
// data. Since this is a heap, we do recursive linear search.
// returns the pointer to the node removed, which would be either the
// same as input (if successfully removed); or NULL (if failed).
LocHeapNode* LocHeapNode::remove(LocHeapNode*& top, LocRankable& data) {
LocHeapNode* removedNode = NULL;
// this is the node, by address
if (&data == (LocRankable*)(top->mData)) {
// pop this node out
removedNode = pop(top);
} else if (!data.outRanks(*top->mData)) {
// subtrees might have this node
if (top->mLeft) {
removedNode = remove(top->mLeft, data);
}
// if we did not find in mLeft, and mRight is not empty
if (!removedNode && top->mRight) {
removedNode = remove(top->mRight, data);
}
// top lost a node in its subtree
if (removedNode) {
top->mSize--;
}
}
return removedNode;
}
// checks if mSize is correct, AND this node is the highest ranking
// of the entire subtree
bool LocHeapNode::checkNodes() {
// size of the current subtree
int totalSize = mSize;
if (mLeft) {
// check the consistency of left subtree
if (mLeft->outRanks(*this) || !mLeft->checkNodes()) {
return false;
}
// subtract the size of left subtree (with subtree head)
totalSize -= mLeft->mSize;
}
if (mRight) {
// check the consistency of right subtree
if (mRight->outRanks(*this) || !mRight->checkNodes()) {
return false;
}
// subtract the size of right subtree (with subtree head)
totalSize -= mRight->mSize;
}
// for the tree nodes to consistent, totalSize must be 1 now
return totalSize == 1;
}
LocHeap::~LocHeap() {
if (mTree) {
delete mTree;
}
}
void LocHeap::push(LocRankable& node) {
LocHeapNode* heapNode = new LocHeapNode(node);
if (!mTree) {
mTree = heapNode;
} else {
mTree->push(*heapNode);
}
}
LocRankable* LocHeap::peek() {
LocRankable* top = NULL;
if (mTree) {
top = mTree->mData;
}
return top;
}
LocRankable* LocHeap::pop() {
LocRankable* locNode = NULL;
if (mTree) {
// mTree may become NULL after this call
LocHeapNode* heapNode = LocHeapNode::pop(mTree);
locNode = heapNode->detachData();
delete heapNode;
}
return locNode;
}
LocRankable* LocHeap::remove(LocRankable& rankable) {
LocRankable* locNode = NULL;
if (mTree) {
// mTree may become NULL after this call
LocHeapNode* heapNode = LocHeapNode::remove(mTree, rankable);
if (heapNode) {
locNode = heapNode->detachData();
delete heapNode;
}
}
return locNode;
}
} // namespace loc_util
#ifdef __LOC_UNIT_TEST__
bool LocHeap::checkTree() {
return ((NULL == mTree) || mTree->checkNodes());
}
uint32_t LocHeap::getTreeSize() {
return (NULL == mTree) ? 0 : mTree->getSize();
}
#endif

100
gps/utils/LocHeap.h Normal file
View file

@ -0,0 +1,100 @@
/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __LOC_HEAP__
#define __LOC_HEAP__
#include <stddef.h>
#include <string.h>
namespace loc_util {
// abstract class to be implemented by client to provide a rankable class
class LocRankable {
public:
virtual inline ~LocRankable() {}
// method to rank objects of such type for sorting purposes.
// The pointer of the input node would be stored in the heap.
// >0 if ranks higher than the input;
// ==0 if equally ranks with the input;
// <0 if ranks lower than the input
virtual int ranks(LocRankable& rankable) = 0;
// convenient method to rank objects of such type for sorting purposes.
inline bool outRanks(LocRankable& rankable) { return ranks(rankable) > 0; }
};
// opaque class to provide service implementation.
class LocHeapNode;
// a heap whose left and right children are not sorted. It is sorted only vertically,
// i.e. parent always ranks higher than children, if they exist. Ranking algorithm is
// implemented in Rankable. The reason that there is no sort between children is to
// help beter balance the tree with lower cost. When a node is pushed to the tree,
// it is guaranteed that the subtree that is smaller gets to have the new node.
class LocHeap {
protected:
LocHeapNode* mTree;
public:
inline LocHeap() : mTree(NULL) {}
~LocHeap();
// push keeps the tree sorted by rank, it also tries to balance the
// tree by adding the new node to the smaller of the subtrees.
// node is reference to an obj that is managed by client, that client
// creates and destroyes. The destroy should happen after the
// node is popped out from the heap.
void push(LocRankable& node);
// Peeks the node data on tree top, which has currently the highest ranking
// There is no change the tree structure with this operation
// Returns NULL if the tree is empty, otherwise pointer to the node data of
// the tree top.
LocRankable* peek();
// pop keeps the tree sorted by rank, but it does not try to balance
// the tree.
// Return - pointer to the node popped out, or NULL if heap is already empty
LocRankable* pop();
// navigating through the tree and find the node that ranks the same
// as the input data, then remove it from the tree. Rank is implemented
// by rankable obj.
// returns the pointer to the node removed; or NULL (if failed).
LocRankable* remove(LocRankable& rankable);
#ifdef __LOC_UNIT_TEST__
bool checkTree();
uint32_t getTreeSize();
#endif
};
} // namespace loc_util
#endif //__LOC_HEAP__

430
gps/utils/LocIpc.cpp Normal file
View file

@ -0,0 +1,430 @@
/* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <netinet/in.h>
#include <netdb.h>
#include <loc_misc_utils.h>
#include <log_util.h>
#include <LocIpc.h>
#include <algorithm>
using namespace std;
namespace loc_util {
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "LocSvc_LocIpc"
#define SOCK_OP_AND_LOG(buf, length, opable, rtv, exe) \
if (nullptr == (buf) || 0 == (length)) { \
LOC_LOGe("Invalid inputs: buf - %p, length - %u", (buf), (length)); \
} else if (!(opable)) { \
LOC_LOGe("Invalid object: operable - %d", (opable)); \
} else { \
rtv = (exe); \
if (-1 == rtv) { \
LOC_LOGw("failed reason: %s", strerror(errno)); \
} \
}
const char Sock::MSG_ABORT[] = "LocIpc::Sock::ABORT";
const char Sock::LOC_IPC_HEAD[] = "$MSGLEN$";
ssize_t Sock::send(const void *buf, uint32_t len, int flags, const struct sockaddr *destAddr,
socklen_t addrlen) const {
ssize_t rtv = -1;
SOCK_OP_AND_LOG(buf, len, isValid(), rtv, sendto(buf, len, flags, destAddr, addrlen));
return rtv;
}
ssize_t Sock::recv(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb, int flags,
struct sockaddr *srcAddr, socklen_t *addrlen, int sid) const {
ssize_t rtv = -1;
if (-1 == sid) {
sid = mSid;
} // else it sid would be connection based socket id for recv
SOCK_OP_AND_LOG(dataCb.get(), mMaxTxSize, isValid(), rtv,
recvfrom(recver, dataCb, sid, flags, srcAddr, addrlen));
return rtv;
}
ssize_t Sock::sendto(const void *buf, size_t len, int flags, const struct sockaddr *destAddr,
socklen_t addrlen) const {
ssize_t rtv = -1;
if (len <= mMaxTxSize) {
rtv = ::sendto(mSid, buf, len, flags, destAddr, addrlen);
} else {
std::string head(LOC_IPC_HEAD + to_string(len));
rtv = ::sendto(mSid, head.c_str(), head.length(), flags, destAddr, addrlen);
if (rtv > 0) {
for (size_t offset = 0; offset < len && rtv > 0; offset += rtv) {
rtv = ::sendto(mSid, (char*)buf + offset, min(len - offset, (size_t)mMaxTxSize),
flags, destAddr, addrlen);
}
rtv = (rtv > 0) ? (head.length() + len) : -1;
}
}
return rtv;
}
ssize_t Sock::recvfrom(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb,
int sid, int flags, struct sockaddr *srcAddr, socklen_t *addrlen) const {
std::string msg(mMaxTxSize, 0);
ssize_t nBytes = ::recvfrom(sid, (void*)msg.data(), msg.size(), flags, srcAddr, addrlen);
if (nBytes > 0) {
if (strncmp(msg.data(), MSG_ABORT, sizeof(MSG_ABORT)) == 0) {
LOC_LOGi("recvd abort msg.data %s", msg.data());
nBytes = 0;
} else if (strncmp(msg.data(), LOC_IPC_HEAD, sizeof(LOC_IPC_HEAD) - 1)) {
// short message
msg.resize(nBytes);
dataCb->onReceive(msg.data(), nBytes, &recver);
} else {
// long message
size_t msgLen = 0;
sscanf(msg.data() + sizeof(LOC_IPC_HEAD) - 1, "%zu", &msgLen);
msg.resize(msgLen);
for (size_t msgLenReceived = 0; (msgLenReceived < msgLen) && (nBytes > 0);
msgLenReceived += nBytes) {
nBytes = ::recvfrom(sid, &(msg[msgLenReceived]), msg.size() - msgLenReceived,
flags, srcAddr, addrlen);
}
if (nBytes > 0) {
nBytes = msgLen;
dataCb->onReceive(msg.data(), nBytes, &recver);
}
}
}
return nBytes;
}
ssize_t Sock::sendAbort(int flags, const struct sockaddr *destAddr, socklen_t addrlen) {
return send(MSG_ABORT, sizeof(MSG_ABORT), flags, destAddr, addrlen);
}
class LocIpcLocalSender : public LocIpcSender {
protected:
shared_ptr<Sock> mSock;
struct sockaddr_un mAddr;
inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); }
inline virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
}
public:
inline LocIpcLocalSender(const char* name) : LocIpcSender(),
mSock(nullptr),
mAddr({.sun_family = AF_UNIX, {}}) {
int fd = -1;
if (nullptr != name) {
fd = ::socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd >= 0) {
timeval timeout;
timeout.tv_sec = 2;
timeout.tv_usec = 0;
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
}
}
mSock.reset(new Sock(fd));
if (mSock != nullptr && mSock->isValid()) {
snprintf(mAddr.sun_path, sizeof(mAddr.sun_path), "%s", name);
}
}
};
class LocIpcLocalRecver : public LocIpcLocalSender, 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 LocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener, const char* name) :
LocIpcLocalSender(name), LocIpcRecver(listener, *this) {
if ((unlink(mAddr.sun_path) < 0) && (errno != ENOENT)) {
LOC_LOGw("unlink socket error. reason:%s", strerror(errno));
}
umask(0157);
if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) {
LOC_LOGe("bind socket error. sock fd: %d: %s, reason: %s", mSock->mSid,
mAddr.sun_path, strerror(errno));
mSock->close();
}
}
inline virtual ~LocIpcLocalRecver() { unlink(mAddr.sun_path); }
inline virtual const char* getName() const override { return mAddr.sun_path; };
inline virtual void abort() const override {
if (isSendable()) {
mSock->sendAbort(0, (struct sockaddr*)&mAddr, sizeof(mAddr));
}
}
};
class LocIpcInetSender : public LocIpcSender {
protected:
int mSockType;
shared_ptr<Sock> mSock;
const string mName;
sockaddr_in mAddr;
inline virtual bool isOperable() const override { return mSock != nullptr && mSock->isValid(); }
virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
}
public:
inline LocIpcInetSender(const LocIpcInetSender& sender) :
mSockType(sender.mSockType), mSock(sender.mSock),
mName(sender.mName), mAddr(sender.mAddr) {
}
inline LocIpcInetSender(const char* name, int32_t port, int sockType) : LocIpcSender(),
mSockType(sockType),
mSock(make_shared<Sock>((nullptr == name) ? -1 : (::socket(AF_INET, mSockType, 0)))),
mName((nullptr == name) ? "" : name),
mAddr({.sin_family = AF_INET, .sin_port = htons(port),
.sin_addr = {htonl(INADDR_ANY)}}) {
if (mSock != nullptr && mSock->isValid() && nullptr != name) {
struct hostent* hp = gethostbyname(name);
if (nullptr != hp) {
memcpy((char*)&(mAddr.sin_addr.s_addr), hp->h_addr_list[0], hp->h_length);
}
}
}
unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener) override {
return make_unique<SockRecver>(listener, *this, mSock);
}
};
class LocIpcInetTcpSender : public LocIpcInetSender {
protected:
mutable bool mFirstTime;
virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t /* msgId */) const {
if (mFirstTime) {
mFirstTime = false;
::connect(mSock->mSid, (const struct sockaddr*)&mAddr, sizeof(mAddr));
}
return mSock->send(data, length, 0, (struct sockaddr*)&mAddr, sizeof(mAddr));
}
public:
inline LocIpcInetTcpSender(const char* name, int32_t port) :
LocIpcInetSender(name, port, SOCK_STREAM),
mFirstTime(true) {}
};
class LocIpcInetRecver : public LocIpcInetSender, public LocIpcRecver {
int32_t mPort;
protected:
virtual ssize_t recv() const = 0;
public:
inline LocIpcInetRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
int32_t port, int sockType) :
LocIpcInetSender(name, port, sockType), LocIpcRecver(listener, *this),
mPort(port) {
if (mSock->isValid() && ::bind(mSock->mSid, (struct sockaddr*)&mAddr, sizeof(mAddr)) < 0) {
LOC_LOGe("bind socket error. sock fd: %d, reason: %s", mSock->mSid, strerror(errno));
mSock->close();
}
}
inline virtual ~LocIpcInetRecver() {}
inline virtual const char* getName() const override { return mName.data(); };
inline virtual void abort() const override {
if (isSendable()) {
sockaddr_in loopBackAddr = {.sin_family = AF_INET, .sin_port = htons(mPort),
.sin_addr = {htonl(INADDR_LOOPBACK)}};
mSock->sendAbort(0, (struct sockaddr*)&loopBackAddr, sizeof(loopBackAddr));
}
}
inline virtual unique_ptr<LocIpcSender> getLastSender() const override {
return make_unique<LocIpcInetSender>(static_cast<const LocIpcInetSender&>(*this));
}
};
class LocIpcInetTcpRecver : public LocIpcInetRecver {
mutable int32_t mConnFd;
protected:
inline virtual ssize_t recv() const override {
socklen_t size = sizeof(mAddr);
if (-1 == mConnFd && mSock->isValid()) {
if (::listen(mSock->mSid, 3) < 0 ||
(mConnFd = accept(mSock->mSid, (struct sockaddr*)&mAddr, &size)) < 0) {
mSock->close();
mConnFd = -1;
}
}
return mSock->recv(*this, mDataCb, 0, (struct sockaddr*)&mAddr, &size, mConnFd);
}
public:
inline LocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
int32_t port) :
LocIpcInetRecver(listener, name, port, SOCK_STREAM), mConnFd(-1) {}
inline virtual ~LocIpcInetTcpRecver() { if (-1 != mConnFd) ::close(mConnFd);}
};
class LocIpcInetUdpRecver : public LocIpcInetRecver {
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 LocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener, const char* name,
int32_t port) :
LocIpcInetRecver(listener, name, port, SOCK_DGRAM) {}
inline virtual ~LocIpcInetUdpRecver() {}
};
class LocIpcRunnable : public LocRunnable {
bool mAbortCalled;
LocIpc& mLocIpc;
unique_ptr<LocIpcRecver> mIpcRecver;
public:
inline LocIpcRunnable(LocIpc& locIpc, unique_ptr<LocIpcRecver>& ipcRecver) :
mAbortCalled(false),
mLocIpc(locIpc),
mIpcRecver(move(ipcRecver)) {}
inline virtual bool run() override {
if (mIpcRecver != nullptr) {
mLocIpc.startBlockingListening(*(mIpcRecver.get()));
if (!mAbortCalled) {
LOC_LOGw("startListeningBlocking() returned w/o stopBlockingListening() called");
}
}
// return false so the calling thread exits while loop
return false;
}
inline virtual void interrupt() override {
mAbortCalled = true;
if (mIpcRecver != nullptr) {
mIpcRecver->abort();
}
}
};
bool LocIpc::startNonBlockingListening(unique_ptr<LocIpcRecver>& ipcRecver) {
if (ipcRecver != nullptr && ipcRecver->isRecvable()) {
std::string threadName("LocIpc-");
threadName.append(ipcRecver->getName());
return mThread.start(threadName.c_str(), make_shared<LocIpcRunnable>(*this, ipcRecver));
} else {
LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
return false;
}
}
bool LocIpc::startBlockingListening(LocIpcRecver& ipcRecver) {
if (ipcRecver.isRecvable()) {
// inform that the socket is ready to receive message
ipcRecver.onListenerReady();
while (ipcRecver.recvData());
return true;
} else {
LOC_LOGe("ipcRecver is null OR ipcRecver->recvable() is fasle");
return false;
}
}
void LocIpc::stopNonBlockingListening() {
mThread.stop();
}
void LocIpc::stopBlockingListening(LocIpcRecver& ipcRecver) {
if (ipcRecver.isRecvable()) {
ipcRecver.abort();
}
}
bool LocIpc::send(LocIpcSender& sender, const uint8_t data[], uint32_t length, int32_t msgId) {
return sender.sendData(data, length, msgId);
}
shared_ptr<LocIpcSender> LocIpc::getLocIpcLocalSender(const char* localSockName) {
return make_shared<LocIpcLocalSender>(localSockName);
}
unique_ptr<LocIpcRecver> LocIpc::getLocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener,
const char* localSockName) {
return make_unique<LocIpcLocalRecver>(listener, localSockName);
}
static void* sLibQrtrHandle = nullptr;
static const char* sLibQrtrName = "libloc_socket.so";
shared_ptr<LocIpcSender> LocIpc::getLocIpcQrtrSender(int service, int instance) {
typedef shared_ptr<LocIpcSender> (*creator_t) (int, int);
static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
"_ZN8loc_util22createLocIpcQrtrSenderEii");
return (nullptr == creator) ? nullptr : creator(service, instance);
}
unique_ptr<LocIpcRecver> LocIpc::getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
int service, int instance,
const shared_ptr<LocIpcQrtrWatcher>& watcher) {
typedef unique_ptr<LocIpcRecver> (*creator_t)(const shared_ptr<ILocIpcListener>&, int, int,
const shared_ptr<LocIpcQrtrWatcher>& watcher);
static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
#ifdef USE_GLIB
"_ZN8loc_util22createLocIpcQrtrRecverERKSt10shared_ptrINS_15ILocIpcListenerEEiiRKS0_INS_17LocIpcQrtrWatcherEE");
#else
"_ZN8loc_util22createLocIpcQrtrRecverERKNSt3__110shared_ptrINS_15ILocIpcListenerEEEiiRKNS1_INS_17LocIpcQrtrWatcherEEE");
#endif
return (nullptr == creator) ? nullptr : creator(listener, service, instance, watcher);
}
shared_ptr<LocIpcSender> LocIpc::getLocIpcInetTcpSender(const char* serverName, int32_t port) {
return make_shared<LocIpcInetTcpSender>(serverName, port);
}
unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener,
const char* serverName, int32_t port) {
return make_unique<LocIpcInetTcpRecver>(listener, serverName, port);
}
shared_ptr<LocIpcSender> LocIpc::getLocIpcInetUdpSender(const char* serverName, int32_t port) {
return make_shared<LocIpcInetSender>(serverName, port, SOCK_DGRAM);
}
unique_ptr<LocIpcRecver> LocIpc::getLocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener,
const char* serverName, int32_t port) {
return make_unique<LocIpcInetUdpRecver>(listener, serverName, port);
}
pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>
LocIpc::getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener, int instance) {
typedef pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>> (*creator_t)(const shared_ptr<ILocIpcListener>&, int);
static void* sLibEmuHandle = nullptr;
static creator_t creator = (creator_t)dlGetSymFromLib(sLibEmuHandle, "libloc_emu.so",
#ifdef USE_GLIB
"_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPair"\
"ERKSt10shared_ptrIN8loc_util15ILocIpcListenerEEi");
#else
"_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPair"\
"ERKNSt3__110shared_ptrIN8loc_util15ILocIpcListenerEEEi");
#endif
return (nullptr == creator) ?
make_pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>(nullptr, nullptr) :
creator(listener, instance);
}
}

241
gps/utils/LocIpc.h Normal file
View file

@ -0,0 +1,241 @@
/* Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __LOC_IPC__
#define __LOC_IPC__
#include <string>
#include <memory>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unordered_set>
#include <mutex>
#include <LocThread.h>
using namespace std;
namespace loc_util {
class LocIpcRecver;
class LocIpcSender;
class ILocIpcListener {
protected:
inline virtual ~ILocIpcListener() {}
public:
// LocIpc client can overwrite this function to get notification
// when the socket for LocIpc is ready to receive messages.
inline virtual void onListenerReady() {}
virtual void onReceive(const char* data, uint32_t len, const LocIpcRecver* recver) = 0;
};
class LocIpcQrtrWatcher {
const unordered_set<int> mServicesToWatch;
unordered_set<int> mClientsToWatch;
mutex mMutex;
inline bool isInWatch(const unordered_set<int>& idsToWatch, int id) {
return idsToWatch.find(id) != idsToWatch.end();
}
protected:
inline virtual ~LocIpcQrtrWatcher() {}
inline LocIpcQrtrWatcher(unordered_set<int> servicesToWatch)
: mServicesToWatch(servicesToWatch) {}
public:
enum class ServiceStatus { UP, DOWN };
inline bool isServiceInWatch(int serviceId) {
return isInWatch(mServicesToWatch, serviceId);
}
inline bool isClientInWatch(int nodeId) {
lock_guard<mutex> lock(mMutex);
return isInWatch(mClientsToWatch, nodeId);
}
inline void addClientToWatch(int nodeId) {
lock_guard<mutex> lock(mMutex);
mClientsToWatch.emplace(nodeId);
}
virtual void onServiceStatusChange(int sericeId, int instanceId, ServiceStatus status,
const LocIpcSender& sender) = 0;
inline virtual void onClientGone(int nodeId, int portId) {}
inline const unordered_set<int>& getServicesToWatch() { return mServicesToWatch; }
};
class LocIpc {
public:
inline LocIpc() = default;
inline virtual ~LocIpc() {
stopNonBlockingListening();
}
static shared_ptr<LocIpcSender>
getLocIpcLocalSender(const char* localSockName);
static shared_ptr<LocIpcSender>
getLocIpcInetUdpSender(const char* serverName, int32_t port);
static shared_ptr<LocIpcSender>
getLocIpcInetTcpSender(const char* serverName, int32_t port);
static shared_ptr<LocIpcSender>
getLocIpcQrtrSender(int service, int instance);
static unique_ptr<LocIpcRecver>
getLocIpcLocalRecver(const shared_ptr<ILocIpcListener>& listener,
const char* localSockName);
static unique_ptr<LocIpcRecver>
getLocIpcInetUdpRecver(const shared_ptr<ILocIpcListener>& listener,
const char* serverName, int32_t port);
static unique_ptr<LocIpcRecver>
getLocIpcInetTcpRecver(const shared_ptr<ILocIpcListener>& listener,
const char* serverName, int32_t port);
inline static unique_ptr<LocIpcRecver>
getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
int service, int instance) {
const shared_ptr<LocIpcQrtrWatcher> qrtrWatcher = nullptr;
return getLocIpcQrtrRecver(listener, service, instance, qrtrWatcher);
}
static unique_ptr<LocIpcRecver>
getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
int service, int instance,
const shared_ptr<LocIpcQrtrWatcher>& qrtrWatcher);
static pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>
getLocIpcQmiLocServiceSenderRecverPair(const shared_ptr<ILocIpcListener>& listener,
int instance);
// Listen for new messages in current thread. Calling this funciton will
// block current thread.
// The listening can be stopped by calling stopBlockingListening() passing
// in the same ipcRecver obj handle.
static bool startBlockingListening(LocIpcRecver& ipcRecver);
static void stopBlockingListening(LocIpcRecver& ipcRecver);
// Create a new LocThread and listen for new messages in it.
// Calling this function will return immediately and won't block current thread.
// The listening can be stopped by calling stopNonBlockingListening().
bool startNonBlockingListening(unique_ptr<LocIpcRecver>& ipcRecver);
void stopNonBlockingListening();
// Send out a message.
// Call this function to send a message in argument data to socket in argument name.
//
// Argument name contains the name of the target unix socket. data contains the
// message to be sent out. Convert your message to a string before calling this function.
// The function will return true on success, and false on failure.
static bool send(LocIpcSender& sender, const uint8_t data[],
uint32_t length, int32_t msgId = -1);
private:
LocThread mThread;
};
/* this is only when client needs to implement Sender / Recver that are not already provided by
the factor methods prvoided by LocIpc. */
class LocIpcSender {
protected:
LocIpcSender() = default;
virtual bool isOperable() const = 0;
virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t msgId) const = 0;
public:
virtual ~LocIpcSender() = default;
inline bool isSendable() const { return isOperable(); }
inline bool sendData(const uint8_t data[], uint32_t length, int32_t msgId) const {
return isSendable() && (send(data, length, msgId) > 0);
}
virtual unique_ptr<LocIpcRecver> getRecver(const shared_ptr<ILocIpcListener>& listener) {
return nullptr;
}
inline virtual void copyDestAddrFrom(const LocIpcSender& otherSender) {}
};
class LocIpcRecver {
LocIpcSender& mIpcSender;
protected:
const shared_ptr<ILocIpcListener> mDataCb;
inline LocIpcRecver(const shared_ptr<ILocIpcListener>& listener, LocIpcSender& sender) :
mIpcSender(sender), mDataCb(listener) {}
LocIpcRecver(LocIpcRecver const& recver) = delete;
LocIpcRecver& operator=(LocIpcRecver const& recver) = delete;
virtual ssize_t recv() const = 0;
public:
virtual ~LocIpcRecver() = default;
inline bool recvData() const { return isRecvable() && (recv() > 0); }
inline bool isRecvable() const { return mDataCb != nullptr && mIpcSender.isSendable(); }
virtual void onListenerReady() { if (mDataCb != nullptr) mDataCb->onListenerReady(); }
inline virtual unique_ptr<LocIpcSender> getLastSender() const {
return nullptr;
}
virtual void abort() const = 0;
virtual const char* getName() const = 0;
};
class Sock {
static const char MSG_ABORT[];
static const char LOC_IPC_HEAD[];
const uint32_t mMaxTxSize;
ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *destAddr,
socklen_t addrlen) const;
ssize_t recvfrom(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb,
int sid, int flags, struct sockaddr *srcAddr, socklen_t *addrlen) const;
public:
int mSid;
inline Sock(int sid, const uint32_t maxTxSize = 8192) : mMaxTxSize(maxTxSize), mSid(sid) {}
inline ~Sock() { close(); }
inline bool isValid() const { return -1 != mSid; }
ssize_t send(const void *buf, uint32_t len, int flags, const struct sockaddr *destAddr,
socklen_t addrlen) const;
ssize_t recv(const LocIpcRecver& recver, const shared_ptr<ILocIpcListener>& dataCb, int flags,
struct sockaddr *srcAddr, socklen_t *addrlen, int sid = -1) const;
ssize_t sendAbort(int flags, const struct sockaddr *destAddr, socklen_t addrlen);
inline void close() {
if (isValid()) {
::close(mSid);
mSid = -1;
}
}
};
class SockRecver : public LocIpcRecver {
shared_ptr<Sock> mSock;
protected:
inline virtual ssize_t recv() const override {
return mSock->recv(*this, mDataCb, 0, nullptr, nullptr);
}
public:
inline SockRecver(const shared_ptr<ILocIpcListener>& listener,
LocIpcSender& sender, shared_ptr<Sock> sock) :
LocIpcRecver(listener, sender), mSock(sock) {
}
inline virtual const char* getName() const override {
return "SockRecver";
}
inline virtual void abort() const override {}
};
}
#endif //__LOC_IPC__

39
gps/utils/LocLoggerBase.h Normal file
View file

@ -0,0 +1,39 @@
/* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_LOGGER_BASE_H
#define LOC_LOGGER_BASE_H
namespace loc_util {
class LocLoggerBase {
public:
virtual void log() {}
};
}
#endif

81
gps/utils/LocSharedLock.h Normal file
View file

@ -0,0 +1,81 @@
/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __LOC_SHARED_LOCK__
#define __LOC_SHARED_LOCK__
#include <stddef.h>
#ifndef FEATURE_EXTERNAL_AP
#include <cutils/atomic.h>
#endif /* FEATURE_EXTERNAL_AP */
#include <pthread.h>
#ifdef FEATURE_EXTERNAL_AP
#include <atomic>
inline int32_t android_atomic_inc(volatile int32_t *addr)
{
volatile std::atomic_int_least32_t* a = (volatile std::atomic_int_least32_t*)addr;
return std::atomic_fetch_add_explicit(a, 1, std::memory_order_release);
}
inline int32_t android_atomic_dec(volatile int32_t *addr)
{
volatile std::atomic_int_least32_t* a = (volatile std::atomic_int_least32_t*)addr;
return std::atomic_fetch_sub_explicit(a, 1, std::memory_order_release);
}
#endif /* FEATURE_EXTERNAL_AP */
namespace loc_util {
// This is a utility created for use cases such that there are more than
// one client who need to share the same lock, but it is not predictable
// which of these clients is to last to go away. This shared lock deletes
// itself when the last client calls its drop() method. To add a cient,
// this share lock's share() method has to be called, so that the obj
// can maintain an accurate client count.
class LocSharedLock {
volatile int32_t mRef;
pthread_mutex_t mMutex;
inline ~LocSharedLock() { pthread_mutex_destroy(&mMutex); }
public:
// first client to create this LockSharedLock
inline LocSharedLock() : mRef(1) { pthread_mutex_init(&mMutex, NULL); }
// following client(s) are to *share()* this lock created by the first client
inline LocSharedLock* share() { android_atomic_inc(&mRef); return this; }
// whe a client no longer needs this shared lock, drop() shall be called.
inline void drop() { if (1 == android_atomic_dec(&mRef)) delete this; }
// locking the lock to enter critical section
inline void lock() { pthread_mutex_lock(&mMutex); }
// unlocking the lock to leave the critical section
inline void unlock() { pthread_mutex_unlock(&mMutex); }
};
} //namespace loc_util
#endif //__LOC_SHARED_LOCK__

111
gps/utils/LocThread.cpp Normal file
View file

@ -0,0 +1,111 @@
/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <sys/prctl.h>
#include <LocThread.h>
#include <string.h>
#include <string>
#include <thread>
#include <loc_pla.h>
using std::weak_ptr;
using std::shared_ptr;
using std::thread;
using std::string;
namespace loc_util {
class LocThreadDelegate {
static const char defaultThreadName[];
weak_ptr<LocRunnable> mRunnable;
thread mThread;
LocThreadDelegate(const string tName, shared_ptr<LocRunnable> r);
public:
~LocThreadDelegate() {
shared_ptr<LocRunnable> runnable = mRunnable.lock();
if (nullptr != runnable) {
runnable->interrupt();
}
}
inline static LocThreadDelegate* create(const char* tName, shared_ptr<LocRunnable> runnable);
};
const char LocThreadDelegate::defaultThreadName[] = "LocThread";
LocThreadDelegate* LocThreadDelegate::create(const char* tName, shared_ptr<LocRunnable> runnable) {
LocThreadDelegate* threadDelegate = nullptr;
if (nullptr != runnable) {
if (!tName) {
tName = defaultThreadName;
}
char lname[16];
auto nameSize = strlen(tName) + 1;
int len = std::min(sizeof(lname), nameSize) - 1;
memcpy(lname, tName, len);
lname[len] = 0;
threadDelegate = new LocThreadDelegate(lname, runnable);
}
return threadDelegate;
}
LocThreadDelegate::LocThreadDelegate(const string tName, shared_ptr<LocRunnable> runnable) :
mRunnable(runnable),
mThread([tName, runnable] {
prctl(PR_SET_NAME, tName.c_str(), 0, 0, 0);
runnable->prerun();
while (runnable->run());
runnable->postrun();
}) {
mThread.detach();
}
bool LocThread::start(const char* tName, shared_ptr<LocRunnable> runnable) {
bool success = false;
if (!mThread) {
mThread = LocThreadDelegate::create(tName, runnable);
// true only if thread is created successfully
success = (NULL != mThread);
}
return success;
}
void LocThread::stop() {
if (nullptr != mThread) {
delete mThread;
mThread = nullptr;
}
}
} // loc_util

95
gps/utils/LocThread.h Normal file
View file

@ -0,0 +1,95 @@
/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __LOC_THREAD__
#define __LOC_THREAD__
#include <stddef.h>
#include <memory>
using std::shared_ptr;
namespace loc_util {
// abstract class to be implemented by client to provide a runnable class
// which gets scheduled by LocThread
class LocRunnable {
public:
inline LocRunnable() = default;
inline virtual ~LocRunnable() = default;
// The method to be implemented by thread clients
// and be scheduled by LocThread
// This method will be repeated called until it returns false; or
// until thread is stopped.
virtual bool run() = 0;
// The method to be run before thread loop (conditionally repeatedly)
// calls run()
inline virtual void prerun() {}
// The method to be run after thread loop (conditionally repeatedly)
// calls run()
inline virtual void postrun() {}
// The method to wake up the potential blocking thread
// no op if not applicable
inline virtual void interrupt() = 0;
};
// opaque class to provide service implementation.
class LocThreadDelegate;
// A utility class to create a thread and run LocRunnable
// caller passes in.
class LocThread {
LocThreadDelegate* mThread;
public:
inline LocThread() : mThread(NULL) {}
inline virtual ~LocThread() { stop(); }
// client starts thread with a runnable, which implements
// the logics to fun in the created thread context.
// The thread is always detached.
// runnable is an obj managed by client. Client creates and
// frees it (but must be after stop() is called, or
// this LocThread obj is deleted).
// The obj will be deleted by LocThread if start()
// returns true. Else it is client's responsibility
// to delete the object
// Returns 0 if success; false if failure.
bool start(const char* threadName, shared_ptr<LocRunnable> runnable);
void stop();
// thread status check
inline bool isRunning() { return NULL != mThread; }
};
} // loc_util
#endif //__LOC_THREAD__

648
gps/utils/LocTimer.cpp Normal file
View file

@ -0,0 +1,648 @@
/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <sys/timerfd.h>
#include <sys/epoll.h>
#include <log_util.h>
#include <loc_timer.h>
#include <LocTimer.h>
#include <LocHeap.h>
#include <LocThread.h>
#include <LocSharedLock.h>
#include <MsgTask.h>
#ifdef __HOST_UNIT_TEST__
#define EPOLLWAKEUP 0
#define CLOCK_BOOTTIME CLOCK_MONOTONIC
#define CLOCK_BOOTTIME_ALARM CLOCK_MONOTONIC
#endif
namespace loc_util {
/*
There are implementations of 5 classes in this file:
LocTimer, LocTimerDelegate, LocTimerContainer, LocTimerPollTask, LocTimerWrapper
LocTimer - client front end, interface for client to start / stop timers, also
to provide a callback.
LocTimerDelegate - an internal timer entity, which also is a LocRankable obj.
Its life cycle is different than that of LocTimer. It gets
created when LocTimer::start() is called, and gets deleted
when it expires or clients calls the hosting LocTimer obj's
stop() method. When a LocTimerDelegate obj is ticking, it
stays in the corresponding LocTimerContainer. When expired
or stopped, the obj is removed from the container. Since it
is also a LocRankable obj, and LocTimerContainer also is a
heap, its ranks() implementation decides where it is placed
in the heap.
LocTimerContainer - core of the timer service. It is a container (derived from
LocHeap) for LocTimerDelegate (implements LocRankable) objs.
There are 2 of such containers, one for sw timers (or Linux
timers) one for hw timers (or Linux alarms). It adds one of
each (those that expire the soonest) to kernel via services
provided by LocTimerPollTask. All the heap management on the
LocTimerDelegate objs are done in the MsgTask context, such
that synchronization is ensured.
LocTimerPollTask - is a class that wraps timerfd and epoll POXIS APIs. It also
both implements LocRunnalbe with epoll_wait() in the run()
method. It is also a LocThread client, so as to loop the run
method.
LocTimerWrapper - a LocTimer client itself, to implement the existing C API with
APIs, loc_timer_start() and loc_timer_stop().
*/
class LocTimerPollTask;
// This is a multi-functaional class that:
// * extends the LocHeap class for the detection of head update upon add / remove
// events. When that happens, soonest time out changes, so timerfd needs update.
// * contains the timers, and add / remove them into the heap
// * provides and maps 2 of such containers, one for timers (or mSwTimers), one
// for alarms (or mHwTimers);
// * provides a polling thread;
// * provides a MsgTask thread for synchronized add / remove / timer client callback.
class LocTimerContainer : public LocHeap {
// mutex to synchronize getters of static members
static pthread_mutex_t mMutex;
// Container of timers
static LocTimerContainer* mSwTimers;
// Container of alarms
static LocTimerContainer* mHwTimers;
// Msg task to provider msg Q, sender and reader.
static MsgTask* mMsgTask;
// Poll task to provide epoll call and threading to poll.
static LocTimerPollTask* mPollTask;
// timer / alarm fd
int mDevFd;
// ctor
LocTimerContainer(bool wakeOnExpire);
// dtor
~LocTimerContainer();
static MsgTask* getMsgTaskLocked();
static LocTimerPollTask* getPollTaskLocked();
// extend LocHeap and pop if the top outRanks input
LocTimerDelegate* popIfOutRanks(LocTimerDelegate& timer);
// update the timer POSIX calls with updated soonest timer spec
void updateSoonestTime(LocTimerDelegate* priorTop);
public:
// factory method to control the creation of mSwTimers / mHwTimers
static LocTimerContainer* get(bool wakeOnExpire);
LocTimerDelegate* getSoonestTimer();
int getTimerFd();
// add a timer / alarm obj into the container
void add(LocTimerDelegate& timer);
// remove a timer / alarm obj from the container
void remove(LocTimerDelegate& timer);
// handling of timer / alarm expiration
void expire();
};
class TimerRunnable : public LocRunnable {
const int mFd;
public:
inline TimerRunnable(const int fd) : mFd(fd) {}
// The method to be implemented by thread clients
// and be scheduled by LocThread
// This method will be repeated called until it returns false; or
// until thread is stopped.
virtual bool run() override;
// The method to wake up the potential blocking thread
// no op if not applicable
inline virtual void interrupt() { close(mFd); }
};
// This class implements the polling thread that epolls imer / alarm fds.
// The LocRunnable::run() contains the actual polling. The other methods
// will be run in the caller's thread context to add / remove timer / alarm
// fds the kernel, while the polling is blocked on epoll_wait() call.
// Since the design is that we have maximally 2 polls, one for all the
// timers; one for all the alarms, we will poll at most on 2 fds. But it
// is possile that all we have are only timers or alarms at one time, so we
// allow dynamically add / remove fds we poll on. The design decision of
// having 1 fd per container of timer / alarm is such that, we may not need
// to make a system call each time a timer / alarm is added / removed, unless
// that changes the "soonest" time out of that of all the timers / alarms.
class LocTimerPollTask {
// the epoll fd
const int mFd;
// the thread that calls TimerRunnable::run() method, where
// epoll_wait() is blocking and waiting for events..
LocThread mThread;
public:
// ctor
LocTimerPollTask();
// dtor
~LocTimerPollTask() = default;
// add a container of timers. Each contain has a unique device fd, i.e.
// either timer or alarm fd, and a heap of timers / alarms. It is expected
// that container would have written to the device fd with the soonest
// time out value in the heap at the time of calling this method. So all
// this method does is to add the fd of the input container to the poll
// and also add the pointer of the container to the event data ptr, such
// when poll_wait wakes up on events, we know who is the owner of the fd.
void addPoll(LocTimerContainer& timerContainer);
// remove a fd that is assciated with a container. The expectation is that
// the atual timer would have been removed from the container.
void removePoll(LocTimerContainer& timerContainer);
};
// Internal class of timer obj. It gets born when client calls LocTimer::start();
// and gets deleted when client calls LocTimer::stop() or when the it expire()'s.
// This class implements LocRankable::ranks() so that when an obj is added into
// the container (of LocHeap), it gets placed in sorted order.
class LocTimerDelegate : public LocRankable {
friend class LocTimerContainer;
friend class LocTimer;
LocTimer* mClient;
LocSharedLock* mLock;
struct timespec mFutureTime;
LocTimerContainer* mContainer;
// not a complete obj, just ctor for LocRankable comparisons
inline LocTimerDelegate(struct timespec& delay)
: mClient(NULL), mLock(NULL), mFutureTime(delay), mContainer(NULL) {}
inline ~LocTimerDelegate() { if (mLock) { mLock->drop(); mLock = NULL; } }
public:
LocTimerDelegate(LocTimer& client, struct timespec& futureTime, LocTimerContainer* container);
void destroyLocked();
// LocRankable virtual method
virtual int ranks(LocRankable& rankable);
void expire();
inline struct timespec getFutureTime() { return mFutureTime; }
};
/***************************LocTimerContainer methods***************************/
// Most of these static recources are created on demand. They however are never
// destoyed. The theory is that there are processes that link to this util lib
// but never use timer, then these resources would never need to be created.
// For those processes that do use timer, it will likely also need to every
// once in a while. It might be cheaper keeping them around.
pthread_mutex_t LocTimerContainer::mMutex = PTHREAD_MUTEX_INITIALIZER;
LocTimerContainer* LocTimerContainer::mSwTimers = NULL;
LocTimerContainer* LocTimerContainer::mHwTimers = NULL;
MsgTask* LocTimerContainer::mMsgTask = NULL;
LocTimerPollTask* LocTimerContainer::mPollTask = NULL;
// ctor - initialize timer heaps
// A container for swTimer (timer) is created, when wakeOnExpire is true; or
// HwTimer (alarm), when wakeOnExpire is false.
LocTimerContainer::LocTimerContainer(bool wakeOnExpire) :
mDevFd(timerfd_create(wakeOnExpire ? CLOCK_BOOTTIME_ALARM : CLOCK_BOOTTIME, 0)) {
if ((-1 == mDevFd) && (errno == EINVAL)) {
LOC_LOGW("%s: timerfd_create failure, fallback to CLOCK_MONOTONIC - %s",
__FUNCTION__, strerror(errno));
mDevFd = timerfd_create(CLOCK_MONOTONIC, 0);
}
if (-1 != mDevFd) {
// ensure we have the necessary resources created
LocTimerContainer::getPollTaskLocked();
LocTimerContainer::getMsgTaskLocked();
} else {
LOC_LOGE("%s: timerfd_create failure - %s", __FUNCTION__, strerror(errno));
}
}
// dtor
// we do not ever destroy the static resources.
inline
LocTimerContainer::~LocTimerContainer() {
close(mDevFd);
}
LocTimerContainer* LocTimerContainer::get(bool wakeOnExpire) {
// get the reference of either mHwTimer or mSwTimers per wakeOnExpire
LocTimerContainer*& container = wakeOnExpire ? mHwTimers : mSwTimers;
// it is cheap to check pointer first than locking mutext unconditionally
if (!container) {
pthread_mutex_lock(&mMutex);
// let's check one more time to be safe
if (!container) {
container = new LocTimerContainer(wakeOnExpire);
// timerfd_create failure
if (-1 == container->getTimerFd()) {
delete container;
container = NULL;
}
}
pthread_mutex_unlock(&mMutex);
}
return container;
}
MsgTask* LocTimerContainer::getMsgTaskLocked() {
// it is cheap to check pointer first than locking mutext unconditionally
if (!mMsgTask) {
mMsgTask = new MsgTask("LocTimerMsgTask");
}
return mMsgTask;
}
LocTimerPollTask* LocTimerContainer::getPollTaskLocked() {
// it is cheap to check pointer first than locking mutext unconditionally
if (!mPollTask) {
mPollTask = new LocTimerPollTask();
}
return mPollTask;
}
inline
LocTimerDelegate* LocTimerContainer::getSoonestTimer() {
return (LocTimerDelegate*)(peek());
}
inline
int LocTimerContainer::getTimerFd() {
return mDevFd;
}
void LocTimerContainer::updateSoonestTime(LocTimerDelegate* priorTop) {
LocTimerDelegate* curTop = getSoonestTimer();
// check if top has changed
if (curTop != priorTop) {
struct itimerspec delay;
memset(&delay, 0, sizeof(struct itimerspec));
bool toSetTime = false;
// if tree is empty now, we remove poll and disarm timer
if (!curTop) {
mPollTask->removePoll(*this);
// setting the values to disarm timer
delay.it_value.tv_sec = 0;
delay.it_value.tv_nsec = 0;
toSetTime = true;
} else if (!priorTop || curTop->outRanks(*priorTop)) {
// do this first to avoid race condition, in case settime is called
// with too small an interval
mPollTask->addPoll(*this);
delay.it_value = curTop->getFutureTime();
toSetTime = true;
}
if (toSetTime) {
timerfd_settime(getTimerFd(), TFD_TIMER_ABSTIME, &delay, NULL);
}
}
}
// all the heap management is done in the MsgTask context.
inline
void LocTimerContainer::add(LocTimerDelegate& timer) {
struct MsgTimerPush : public LocMsg {
LocTimerContainer* mTimerContainer;
LocTimerDelegate* mTimer;
inline MsgTimerPush(LocTimerContainer& container, LocTimerDelegate& timer) :
LocMsg(), mTimerContainer(&container), mTimer(&timer) {}
inline virtual void proc() const {
LocTimerDelegate* priorTop = mTimerContainer->getSoonestTimer();
mTimerContainer->push((LocRankable&)(*mTimer));
mTimerContainer->updateSoonestTime(priorTop);
}
};
mMsgTask->sendMsg(new MsgTimerPush(*this, timer));
}
// all the heap management is done in the MsgTask context.
void LocTimerContainer::remove(LocTimerDelegate& timer) {
struct MsgTimerRemove : public LocMsg {
LocTimerContainer* mTimerContainer;
LocTimerDelegate* mTimer;
inline MsgTimerRemove(LocTimerContainer& container, LocTimerDelegate& timer) :
LocMsg(), mTimerContainer(&container), mTimer(&timer) {}
inline virtual void proc() const {
LocTimerDelegate* priorTop = mTimerContainer->getSoonestTimer();
// update soonest timer only if mTimer is actually removed from
// mTimerContainer AND mTimer is not priorTop.
if (priorTop == ((LocHeap*)mTimerContainer)->remove((LocRankable&)*mTimer)) {
// if passing in NULL, we tell updateSoonestTime to update
// kernel with the current top timer interval.
mTimerContainer->updateSoonestTime(NULL);
}
// all timers are deleted here, and only here.
delete mTimer;
}
};
mMsgTask->sendMsg(new MsgTimerRemove(*this, timer));
}
// all the heap management is done in the MsgTask context.
// Upon expire, we check and continuously pop the heap until
// the top node's timeout is in the future.
void LocTimerContainer::expire() {
struct MsgTimerExpire : public LocMsg {
LocTimerContainer* mTimerContainer;
inline MsgTimerExpire(LocTimerContainer& container) :
LocMsg(), mTimerContainer(&container) {}
inline virtual void proc() const {
struct timespec now;
// get time spec of now
clock_gettime(CLOCK_BOOTTIME, &now);
LocTimerDelegate timerOfNow(now);
// pop everything in the heap that outRanks now, i.e. has time older than now
// and then call expire() on that timer.
for (LocTimerDelegate* timer = (LocTimerDelegate*)mTimerContainer->pop();
NULL != timer;
timer = mTimerContainer->popIfOutRanks(timerOfNow)) {
// the timer delegate obj will be deleted before the return of this call
timer->expire();
}
mTimerContainer->updateSoonestTime(NULL);
}
};
struct itimerspec delay;
memset(&delay, 0, sizeof(struct itimerspec));
timerfd_settime(getTimerFd(), TFD_TIMER_ABSTIME, &delay, NULL);
mPollTask->removePoll(*this);
mMsgTask->sendMsg(new MsgTimerExpire(*this));
}
LocTimerDelegate* LocTimerContainer::popIfOutRanks(LocTimerDelegate& timer) {
LocTimerDelegate* poppedNode = NULL;
if (mTree && !timer.outRanks(*peek())) {
poppedNode = (LocTimerDelegate*)(pop());
}
return poppedNode;
}
/***************************LocTimerPollTask methods***************************/
inline
LocTimerPollTask::LocTimerPollTask()
: mFd(epoll_create(2)), mThread() {
// before a next call returens, a thread will be created. The run() method
// could already be running in parallel. Also, since each of the objs
// creates a thread, the container will make sure that there will be only
// one of such obj for our timer implementation.
mThread.start("LocTimerPollTask", std::make_shared<TimerRunnable>(mFd));
}
void LocTimerPollTask::addPoll(LocTimerContainer& timerContainer) {
struct epoll_event ev;
memset(&ev, 0, sizeof(ev));
ev.events = EPOLLIN;
ev.data.fd = timerContainer.getTimerFd();
// it is important that we set this context pointer with the input
// timer container this is how we know which container should handle
// which expiration.
ev.data.ptr = &timerContainer;
epoll_ctl(mFd, EPOLL_CTL_ADD, timerContainer.getTimerFd(), &ev);
}
inline
void LocTimerPollTask::removePoll(LocTimerContainer& timerContainer) {
epoll_ctl(mFd, EPOLL_CTL_DEL, timerContainer.getTimerFd(), NULL);
}
// The polling thread context will call this method. If run() method needs to
// be repetitvely called, it must return true from the previous call.
bool TimerRunnable::run() {
struct epoll_event ev[2];
// we have max 2 descriptors to poll from
int fds = epoll_wait(mFd, ev, 2, -1);
// we pretty much want to continually poll until the fd is closed
bool rerun = (fds > 0) || (errno == EINTR);
if (fds > 0) {
// we may have 2 events
for (int i = 0; i < fds; i++) {
// each fd has a context pointer associated with the right timer container
LocTimerContainer* container = (LocTimerContainer*)(ev[i].data.ptr);
if (container) {
container->expire();
} else {
epoll_ctl(mFd, EPOLL_CTL_DEL, ev[i].data.fd, NULL);
}
}
}
// if rerun is true, we are requesting to be scheduled again
return rerun;
}
/***************************LocTimerDelegate methods***************************/
inline
LocTimerDelegate::LocTimerDelegate(LocTimer& client,
struct timespec& futureTime,
LocTimerContainer* container)
: mClient(&client),
mLock(mClient->mLock->share()),
mFutureTime(futureTime),
mContainer(container) {
// adding the timer into the container
mContainer->add(*this);
}
inline
void LocTimerDelegate::destroyLocked() {
// client handle will likely be deleted soon after this
// method returns. Nulling this handle so that expire()
// won't call the callback on the dead handle any more.
mClient = NULL;
if (mContainer) {
LocTimerContainer* container = mContainer;
mContainer = NULL;
if (container) {
container->remove(*this);
}
} // else we do not do anything. No such *this* can be
// created and reached here with mContainer ever been
// a non NULL. So *this* must have reached the if clause
// once, and we want it reach there only once.
}
int LocTimerDelegate::ranks(LocRankable& rankable) {
int rank = -1;
LocTimerDelegate* timer = (LocTimerDelegate*)(&rankable);
if (timer) {
// larger time ranks lower!!!
// IOW, if input obj has bigger tv_sec/tv_nsec, this obj outRanks higher
rank = timer->mFutureTime.tv_sec - mFutureTime.tv_sec;
if(0 == rank)
{
//rank against tv_nsec for msec accuracy
rank = (int)(timer->mFutureTime.tv_nsec - mFutureTime.tv_nsec);
}
}
return rank;
}
inline
void LocTimerDelegate::expire() {
// keeping a copy of client pointer to be safe
// when timeOutCallback() is called at the end of this
// method, *this* obj may be already deleted.
LocTimer* client = mClient;
// force a stop, which will lead to delete of this obj
if (client && client->stop()) {
// calling client callback with a pointer save on the stack
// only if stop() returns true, i.e. it hasn't been stopped
// already.
client->timeOutCallback();
}
}
/***************************LocTimer methods***************************/
LocTimer::LocTimer() : mTimer(NULL), mLock(new LocSharedLock()) {
}
LocTimer::~LocTimer() {
stop();
if (mLock) {
mLock->drop();
mLock = NULL;
}
}
bool LocTimer::start(unsigned int timeOutInMs, bool wakeOnExpire) {
bool success = false;
mLock->lock();
if (!mTimer) {
struct timespec futureTime;
clock_gettime(CLOCK_BOOTTIME, &futureTime);
futureTime.tv_sec += timeOutInMs / 1000;
futureTime.tv_nsec += (timeOutInMs % 1000) * 1000000;
if (futureTime.tv_nsec >= 1000000000) {
futureTime.tv_sec += futureTime.tv_nsec / 1000000000;
futureTime.tv_nsec %= 1000000000;
}
LocTimerContainer* container;
container = LocTimerContainer::get(wakeOnExpire);
if (NULL != container) {
mTimer = new LocTimerDelegate(*this, futureTime, container);
// if mTimer is non 0, success should be 0; or vice versa
}
success = (NULL != mTimer);
}
mLock->unlock();
return success;
}
bool LocTimer::stop() {
bool success = false;
mLock->lock();
if (mTimer) {
LocTimerDelegate* timer = mTimer;
mTimer = NULL;
if (timer) {
timer->destroyLocked();
success = true;
}
}
mLock->unlock();
return success;
}
/***************************LocTimerWrapper methods***************************/
//////////////////////////////////////////////////////////////////////////
// This section below wraps for the C style APIs
//////////////////////////////////////////////////////////////////////////
class LocTimerWrapper : public LocTimer {
loc_timer_callback mCb;
void* mCallerData;
LocTimerWrapper* mMe;
static pthread_mutex_t mMutex;
inline ~LocTimerWrapper() { mCb = NULL; mMe = NULL; }
public:
inline LocTimerWrapper(loc_timer_callback cb, void* callerData) :
mCb(cb), mCallerData(callerData), mMe(this) {
}
void destroy() {
pthread_mutex_lock(&mMutex);
if (NULL != mCb && this == mMe) {
delete this;
}
pthread_mutex_unlock(&mMutex);
}
virtual void timeOutCallback() {
loc_timer_callback cb = mCb;
void* callerData = mCallerData;
if (cb) {
cb(callerData, 0);
}
destroy();
}
};
} // namespace loc_util
//////////////////////////////////////////////////////////////////////////
// This section below wraps for the C style APIs
//////////////////////////////////////////////////////////////////////////
using loc_util::LocTimerWrapper;
pthread_mutex_t LocTimerWrapper::mMutex = PTHREAD_MUTEX_INITIALIZER;
void* loc_timer_start(uint64_t msec, loc_timer_callback cb_func,
void *caller_data, bool wake_on_expire)
{
LocTimerWrapper* locTimerWrapper = NULL;
if (cb_func) {
locTimerWrapper = new LocTimerWrapper(cb_func, caller_data);
if (locTimerWrapper) {
locTimerWrapper->start(msec, wake_on_expire);
}
}
return locTimerWrapper;
}
void loc_timer_stop(void*& handle)
{
if (handle) {
LocTimerWrapper* locTimerWrapper = (LocTimerWrapper*)(handle);
locTimerWrapper->destroy();
handle = NULL;
}
}

78
gps/utils/LocTimer.h Normal file
View file

@ -0,0 +1,78 @@
/* Copyright (c) 2015, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __LOC_TIMER_CPP_H__
#define __LOC_TIMER_CPP_H__
#include <stddef.h>
#include <loc_pla.h>
namespace loc_util {
// opaque class to provide service implementation.
class LocTimerDelegate;
class LocSharedLock;
// LocTimer client must extend this class and implementthe callback.
// start() / stop() methods are to arm / disarm timer.
class LocTimer
{
LocTimerDelegate* mTimer;
LocSharedLock* mLock;
// don't really want mLock to be manipulated by clients, yet LocTimer
// has to have a reference to the lock so that the delete of LocTimer
// and LocTimerDelegate can work together on their share resources.
friend class LocTimerDelegate;
public:
LocTimer();
virtual ~LocTimer();
// timeOutInMs: timeout delay in ms
// wakeOnExpire: true if to wake up CPU (if sleeping) upon timer
// expiration and notify the client.
// false if to wait until next time CPU wakes up (if
// sleeping) and then notify the client.
// return: true on success;
// false on failure, e.g. timer is already running.
bool start(uint32_t timeOutInMs, bool wakeOnExpire);
// return: true on success;
// false on failure, e.g. timer is not running.
bool stop();
// LocTimer client Should implement this method.
// This method is used for timeout calling back to client. This method
// should be short enough (eg: send a message to your own thread).
virtual void timeOutCallback() = 0;
};
} // namespace loc_util
#endif //__LOC_DELAY_H__

View file

@ -0,0 +1,201 @@
/* Copyright (c) 2015, 2017, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __LOC_UNORDERDED_SETMAP_H__
#define __LOC_UNORDERDED_SETMAP_H__
#include <algorithm>
#include <loc_pla.h>
#ifdef NO_UNORDERED_SET_OR_MAP
#include <set>
#include <map>
#else
#include <unordered_set>
#include <unordered_map>
#endif
using std::unordered_set;
using std::unordered_map;
namespace loc_util {
// Trim from *fromSet* any elements that also exist in *rVals*.
// The optional *goneVals*, if not null, will be populated with removed elements.
template <typename T>
inline static void trimSet(unordered_set<T>& fromSet, const unordered_set<T>& rVals,
unordered_set<T>* goneVals) {
for (auto val : rVals) {
if (fromSet.erase(val) > 0 && nullptr != goneVals) {
goneVals->insert(val);
}
}
}
// this method is destructive to the input unordered_sets.
// the return set is the interset extracted out from the two input sets, *s1* and *s2*.
// *s1* and *s2* will be left with the intersect removed from them.
template <typename T>
static unordered_set<T> removeAndReturnInterset(unordered_set<T>& s1, unordered_set<T>& s2) {
unordered_set<T> common = {};
for (auto b = s2.begin(); b != s2.end(); b++) {
auto a = find(s1.begin(), s1.end(), *b);
if (a != s1.end()) {
// this is a common item of both l1 and l2, remove from both
// but after we add to common
common.insert(*a);
s1.erase(a);
s2.erase(b);
}
}
return common;
}
template <typename KEY, typename VAL>
class LocUnorderedSetMap {
unordered_map<KEY, unordered_set<VAL>> mMap;
// Trim the VALs pointed to by *iter*, with everything that also exist in *rVals*.
// If the set becomes empty, remove the map entry. *goneVals*, if not null, records
// the trimmed VALs.
bool trimOrRemove(typename unordered_map<KEY, unordered_set<VAL>>::iterator iter,
const unordered_set<VAL>& rVals, unordered_set<VAL>* goneVals) {
trimSet<VAL>(iter->second, rVals, goneVals);
bool removeEntry = (iter->second.empty());
if (removeEntry) {
mMap.erase(iter);
}
return removeEntry;
}
public:
inline LocUnorderedSetMap() {}
inline LocUnorderedSetMap(size_t size) : LocUnorderedSetMap() {
mMap.get_allocator().allocate(size);
}
inline bool empty() { return mMap.empty(); }
// This gets the raw pointer to the VALs pointed to by *key*
// If the entry is not in the map, nullptr will be returned.
inline unordered_set<VAL>* getValSetPtr(const KEY& key) {
auto entry = mMap.find(key);
return (entry != mMap.end()) ? &(entry->second) : nullptr;
}
// This gets a copy of VALs pointed to by *key*
// If the entry is not in the map, an empty set will be returned.
inline unordered_set<VAL> getValSet(const KEY& key) {
auto entry = mMap.find(key);
return (entry != mMap.end()) ? entry->second : unordered_set<VAL>{};
}
// This gets all the KEYs from the map
inline unordered_set<KEY> getKeys() {
unordered_set<KEY> keys = {};
for (auto entry : mMap) {
keys.insert(entry.first);
}
return keys;
}
inline bool remove(const KEY& key) {
return mMap.erase(key) > 0;
}
// This looks into all the entries keyed by *keys*. Remove any VALs from the entries
// that also exist in *rVals*. If the entry is left with an empty set, the entry will
// be removed. The optional parameters *goneKeys* and *goneVals* will record the KEYs
// (or entries) and the collapsed VALs removed from the map, respectively.
inline void trimOrRemove(unordered_set<KEY>&& keys, const unordered_set<VAL>& rVals,
unordered_set<KEY>* goneKeys, unordered_set<VAL>* goneVals) {
trimOrRemove(keys, rVals, goneKeys, goneVals);
}
inline void trimOrRemove(unordered_set<KEY>& keys, const unordered_set<VAL>& rVals,
unordered_set<KEY>* goneKeys, unordered_set<VAL>* goneVals) {
for (auto key : keys) {
auto iter = mMap.find(key);
if (iter != mMap.end() && trimOrRemove(iter, rVals, goneVals) && nullptr != goneKeys) {
goneKeys->insert(iter->first);
}
}
}
// This adds all VALs from *newVals* to the map entry keyed by *key*. Or if it
// doesn't exist yet, add the set to the map.
bool add(const KEY& key, const unordered_set<VAL>& newVals) {
bool newEntryAdded = false;
if (!newVals.empty()) {
auto iter = mMap.find(key);
if (iter != mMap.end()) {
iter->second.insert(newVals.begin(), newVals.end());
} else {
mMap[key] = newVals;
newEntryAdded = true;
}
}
return newEntryAdded;
}
// This adds to each of entries in the map keyed by *keys* with the VALs in the
// *enwVals*. If there new entries added (new key in *keys*), *newKeys*, if not
// null, would be populated with those keys.
inline void add(const unordered_set<KEY>& keys, const unordered_set<VAL>&& newVals,
unordered_set<KEY>* newKeys) {
add(keys, newVals, newKeys);
}
inline void add(const unordered_set<KEY>& keys, const unordered_set<VAL>& newVals,
unordered_set<KEY>* newKeys) {
for (auto key : keys) {
if (add(key, newVals) && nullptr != newKeys) {
newKeys->insert(key);
}
}
}
// This puts *newVals* into the map keyed by *key*, and returns the VALs that are
// in effect removed from the keyed VAL set in the map entry.
// This call would also remove those same VALs from *newVals*.
inline unordered_set<VAL> update(const KEY& key, unordered_set<VAL>& newVals) {
unordered_set<VAL> goneVals = {};
if (newVals.empty()) {
mMap.erase(key);
} else {
auto curVals = mMap[key];
mMap[key] = newVals;
goneVals = removeAndReturnInterset(curVals, newVals);
}
return goneVals;
}
};
} // namespace loc_util
#endif // #ifndef __LOC_UNORDERDED_SETMAP_H__

189
gps/utils/LogBuffer.cpp Normal file
View file

@ -0,0 +1,189 @@
/* Copyright (c) 2019 - 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "LogBuffer.h"
#ifdef USE_GLIB
#include <execinfo.h>
#endif
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "LocSvc_LogBuffer"
namespace loc_util {
LogBuffer* LogBuffer::mInstance;
struct sigaction LogBuffer::mOriSigAction[NSIG];
struct sigaction LogBuffer::mNewSigAction;
mutex LogBuffer::sLock;
LogBuffer* LogBuffer::getInstance() {
if (mInstance == nullptr) {
lock_guard<mutex> guard(sLock);
if (mInstance == nullptr) {
mInstance = new LogBuffer();
}
}
return mInstance;
}
LogBuffer::LogBuffer(): mLogList(TOTAL_LOG_LEVELS),
mConfigVec(TOTAL_LOG_LEVELS, ConfigsInLevel(TIME_DEPTH_THRESHOLD_MINIMAL_IN_SEC,
MAXIMUM_NUM_IN_LIST, 0)) {
loc_param_s_type log_buff_config_table[] =
{
{"E_LEVEL_TIME_DEPTH", &mConfigVec[0].mTimeDepthThres, NULL, 'n'},
{"E_LEVEL_MAX_CAPACITY", &mConfigVec[0].mMaxNumThres, NULL, 'n'},
{"W_LEVEL_TIME_DEPTH", &mConfigVec[1].mTimeDepthThres, NULL, 'n'},
{"W_LEVEL_MAX_CAPACITY", &mConfigVec[1].mMaxNumThres, NULL, 'n'},
{"I_LEVEL_TIME_DEPTH", &mConfigVec[2].mTimeDepthThres, NULL, 'n'},
{"I_LEVEL_MAX_CAPACITY", &mConfigVec[2].mMaxNumThres, NULL, 'n'},
{"D_LEVEL_TIME_DEPTH", &mConfigVec[3].mTimeDepthThres, NULL, 'n'},
{"D_LEVEL_MAX_CAPACITY", &mConfigVec[3].mMaxNumThres, NULL, 'n'},
{"V_LEVEL_TIME_DEPTH", &mConfigVec[4].mTimeDepthThres, NULL, 'n'},
{"V_LEVEL_MAX_CAPACITY", &mConfigVec[4].mMaxNumThres, NULL, 'n'},
};
loc_read_conf(LOC_PATH_GPS_CONF_STR, log_buff_config_table,
sizeof(log_buff_config_table)/sizeof(log_buff_config_table[0]));
registerSignalHandler();
}
void LogBuffer::append(string& data, int level, uint64_t timestamp) {
lock_guard<mutex> guard(mLock);
pair<uint64_t, string> item(timestamp, data);
mLogList.append(item, level);
mConfigVec[level].mCurrentSize++;
while ((timestamp - mLogList.front(level).first) > mConfigVec[level].mTimeDepthThres ||
mConfigVec[level].mCurrentSize > mConfigVec[level].mMaxNumThres) {
mLogList.pop(level);
mConfigVec[level].mCurrentSize--;
}
}
//Dump the log buffer of specific level, level = -1 to dump all the levels in log buffer.
void LogBuffer::dump(std::function<void(stringstream&)> log, int level) {
lock_guard<mutex> guard(mLock);
list<pair<pair<uint64_t, string>, int>> li;
if (-1 == level) {
li = mLogList.dump();
} else {
li = mLogList.dump(level);
}
ALOGE("Begining of dump, buffer size: %d", (int)li.size());
stringstream ln;
ln << "dump log buffer, level[" << level << "]" << ", buffer size: " << li.size() << endl;
log(ln);
for_each (li.begin(), li.end(), [&, this](const pair<pair<uint64_t, string>, int> &item){
stringstream line;
line << "["<<item.first.first << "] ";
line << "Level " << mLevelMap[item.second] << ": ";
line << item.first.second << endl;
if (log != nullptr) {
log(line);
}
});
ALOGE("End of dump");
}
void LogBuffer::dumpToAdbLogcat() {
dump([](stringstream& line){
ALOGE("%s", line.str().c_str());
});
}
void LogBuffer::dumpToLogFile(string filePath) {
ALOGE("Dump GPS log buffer to file: %s", filePath.c_str());
fstream s;
s.open(filePath, std::fstream::out | std::fstream::app);
dump([&s](stringstream& line){
s << line.str();
});
s.close();
}
void LogBuffer::flush() {
mLogList.flush();
}
void LogBuffer::registerSignalHandler() {
ALOGE("Singal handler registered");
mNewSigAction.sa_sigaction = &LogBuffer::signalHandler;
mNewSigAction.sa_flags = SA_SIGINFO | SA_RESTART;
sigemptyset(&mNewSigAction.sa_mask);
sigaction(SIGINT, &mNewSigAction, &mOriSigAction[SIGINT]);
sigaction(SIGKILL, &mNewSigAction, &mOriSigAction[SIGKILL]);
sigaction(SIGSEGV, &mNewSigAction, &mOriSigAction[SIGSEGV]);
sigaction(SIGABRT, &mNewSigAction, &mOriSigAction[SIGABRT]);
sigaction(SIGTRAP, &mNewSigAction, &mOriSigAction[SIGTRAP]);
sigaction(SIGUSR1, &mNewSigAction, &mOriSigAction[SIGUSR1]);
}
void LogBuffer::signalHandler(const int code, siginfo_t *const si, void *const sc) {
ALOGE("[Gnss Log buffer]Singal handler, signal ID: %d", code);
#ifdef USE_GLIB
int nptrs;
void *buffer[100];
char **strings;
nptrs = backtrace(buffer, sizeof(buffer)/sizeof(*buffer));
strings = backtrace_symbols(buffer, nptrs);
if (strings != NULL) {
timespec tv;
clock_gettime(CLOCK_BOOTTIME, &tv);
uint64_t elapsedTime = (uint64_t)tv.tv_sec + (uint64_t)tv.tv_nsec/1000000000;
for (int i = 0; i < nptrs; i++) {
string s(strings[i]);
mInstance->append(s, 0, elapsedTime);
}
}
#endif
//Dump the log buffer to adb logcat
mInstance->dumpToAdbLogcat();
//Dump the log buffer to file
time_t now = time(NULL);
struct tm *curr_time = localtime(&now);
char path[50];
snprintf(path, 50, LOG_BUFFER_FILE_PATH "gpslog_%d%d%d-%d%d%d.log",
(1900 + curr_time->tm_year), ( 1 + curr_time->tm_mon), curr_time->tm_mday,
curr_time->tm_hour, curr_time->tm_min, curr_time->tm_sec);
mInstance->dumpToLogFile(path);
//Process won't be terminated if SIGUSR1 is recieved
if (code != SIGUSR1) {
mOriSigAction[code].sa_sigaction(code, si, sc);
}
}
}

95
gps/utils/LogBuffer.h Normal file
View file

@ -0,0 +1,95 @@
/* Copyright (c) 2019 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOG_BUFFER_H
#define LOG_BUFFER_H
#include "SkipList.h"
#include "log_util.h"
#include <loc_cfg.h>
#include <loc_pla.h>
#include <string>
#include <sstream>
#include <ostream>
#include <fstream>
#include <time.h>
#include <mutex>
#include <signal.h>
#include <thread>
#include <functional>
//default error level time depth threshold,
#define TIME_DEPTH_THRESHOLD_MINIMAL_IN_SEC 60
//default maximum log buffer size
#define MAXIMUM_NUM_IN_LIST 50
//file path of dumped log buffer
#define LOG_BUFFER_FILE_PATH "/data/vendor/location/"
namespace loc_util {
class ConfigsInLevel{
public:
uint32_t mTimeDepthThres;
uint32_t mMaxNumThres;
int mCurrentSize;
ConfigsInLevel(uint32_t time, int num, int size):
mTimeDepthThres(time), mMaxNumThres(num), mCurrentSize(size) {}
};
class LogBuffer {
private:
static LogBuffer* mInstance;
static struct sigaction mOriSigAction[NSIG];
static struct sigaction mNewSigAction;
static mutex sLock;
SkipList<pair<uint64_t, string>> mLogList;
vector<ConfigsInLevel> mConfigVec;
mutex mLock;
const vector<string> mLevelMap {"E", "W", "I", "D", "V"};
public:
static LogBuffer* getInstance();
void append(string& data, int level, uint64_t timestamp);
void dump(std::function<void(stringstream&)> log, int level = -1);
void dumpToAdbLogcat();
void dumpToLogFile(string filePath);
void flush();
private:
LogBuffer();
void registerSignalHandler();
static void signalHandler(const int code, siginfo_t *const si, void *const sc);
};
}
#endif

75
gps/utils/Makefile.am Normal file
View file

@ -0,0 +1,75 @@
ACLOCAL_AMFLAGS = -I m4
AM_CFLAGS = -Wundef \
-MD \
-Wno-trigraphs \
-g -O0 \
-fno-inline \
-fno-short-enums \
-fpic \
-I./ \
-std=c++14 \
$(LOCPLA_CFLAGS)
libgps_utils_la_h_sources = \
msg_q.h \
linked_list.h \
loc_cfg.h \
loc_log.h \
loc_target.h \
loc_timer.h \
MsgTask.h \
LocHeap.h \
LocThread.h \
LocTimer.h \
LocIpc.h \
SkipList.h\
loc_misc_utils.h \
loc_nmea.h \
gps_extended_c.h \
gps_extended.h \
loc_gps.h \
log_util.h \
LocSharedLock.h \
LocUnorderedSetMap.h\
LocLoggerBase.h
libgps_utils_la_c_sources = \
linked_list.c \
msg_q.c \
loc_cfg.cpp \
loc_log.cpp \
loc_target.cpp \
LocHeap.cpp \
LocTimer.cpp \
LocThread.cpp \
LocIpc.cpp \
LogBuffer.cpp \
MsgTask.cpp \
loc_misc_utils.cpp \
loc_nmea.cpp
library_includedir = $(pkgincludedir)
library_include_HEADERS = $(libgps_utils_la_h_sources)
libgps_utils_la_SOURCES = $(libgps_utils_la_c_sources)
if USE_GLIB
libgps_utils_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@
libgps_utils_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0
libgps_utils_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@
else
libgps_utils_la_CFLAGS = $(AM_CFLAGS)
libgps_utils_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0
libgps_utils_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
endif
libgps_utils_la_LIBADD = $(CUTILS_LIBS) -ldl
#Create and Install libraries
lib_LTLIBRARIES = libgps_utils.la
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = gps-utils.pc
EXTRA_DIST = $(pkgconfig_DATA)

120
gps/utils/MsgTask.cpp Normal file
View file

@ -0,0 +1,120 @@
/* Copyright (c) 2011-2013, 2015, 2017, 2020 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.
*
*/
#define LOG_NDEBUG 0
#define LOG_TAG "LocSvc_MsgTask"
#include <unistd.h>
#include <MsgTask.h>
#include <msg_q.h>
#include <log_util.h>
#include <loc_log.h>
#include <loc_pla.h>
namespace loc_util {
class MTRunnable : public LocRunnable {
const void* mQ;
public:
inline MTRunnable(const void* q) : mQ(q) {}
virtual ~MTRunnable();
// Overrides of LocRunnable methods
// This method will be repeated called until it returns false; or
// until thread is stopped.
virtual bool run() override;
// The method to be run before thread loop (conditionally repeatedly)
// calls run()
virtual void prerun() override;
// to interrupt the run() method and come out of that
virtual void interrupt() override;
};
static void LocMsgDestroy(void* msg) {
delete (LocMsg*)msg;
}
MsgTask::MsgTask(const char* threadName) :
mQ(msg_q_init2()), mThread() {
mThread.start(threadName, std::make_shared<MTRunnable>(mQ));
}
void MsgTask::sendMsg(const LocMsg* msg) const {
if (msg && this) {
msg_q_snd((void*)mQ, (void*)msg, LocMsgDestroy);
} else {
LOC_LOGE("%s: msg is %p and this is %p",
__func__, msg, this);
}
}
void MsgTask::sendMsg(const std::function<void()> runnable) const {
struct RunMsg : public LocMsg {
const std::function<void()> mRunnable;
public:
inline RunMsg(const std::function<void()> runnable) : mRunnable(runnable) {}
~RunMsg() = default;
inline virtual void proc() const override { mRunnable(); }
};
sendMsg(new RunMsg(runnable));
}
void MTRunnable::interrupt() {
msg_q_unblock((void*)mQ);
}
void MTRunnable::prerun() {
// make sure we do not run in background scheduling group
set_sched_policy(gettid(), SP_FOREGROUND);
}
bool MTRunnable::run() {
LocMsg* msg;
msq_q_err_type result = msg_q_rcv((void*)mQ, (void **)&msg);
if (eMSG_Q_SUCCESS != result) {
LOC_LOGE("%s:%d] fail receiving msg: %s\n", __func__, __LINE__,
loc_get_msg_q_status(result));
return false;
}
msg->log();
// there is where each individual msg handling is invoked
msg->proc();
delete msg;
return true;
}
MTRunnable::~MTRunnable() {
msg_q_flush((void*)mQ);
msg_q_destroy((void**)&mQ);
}
} // namespace loc_util

56
gps/utils/MsgTask.h Normal file
View file

@ -0,0 +1,56 @@
/* Copyright (c) 2011-2013, 2015, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __MSG_TASK__
#define __MSG_TASK__
#include <functional>
#include <LocThread.h>
namespace loc_util {
struct LocMsg {
inline LocMsg() {}
inline virtual ~LocMsg() {}
virtual void proc() const = 0;
inline virtual void log() const {}
};
class MsgTask {
const void* mQ;
LocThread mThread;
public:
~MsgTask() = default;
MsgTask(const char* threadName = NULL);
void sendMsg(const LocMsg* msg) const;
void sendMsg(const std::function<void()> runnable) const;
};
} //
#endif //__MSG_TASK__

158
gps/utils/SkipList.h Normal file
View file

@ -0,0 +1,158 @@
/* Copyright (c) 2019 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_SKIP_LIST_H
#define LOC_SKIP_LIST_H
#include <stdlib.h>
#include <list>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
namespace loc_util {
template <typename T,
template<typename elem, typename Allocator = std::allocator<elem>> class container = list>
class SkipNode {
public:
typedef typename container<SkipNode<T, container>>::iterator NodeIterator;
int mLevel;
T mData;
NodeIterator mNextInLevel;
SkipNode(int level, T& data): mLevel(level), mData(data) {}
};
template <typename T>
class SkipList {
using NodeIterator = typename SkipNode<T>::NodeIterator;
private:
list<SkipNode<T>> mMainList;
vector<NodeIterator> mHeadVec;
vector<NodeIterator> mTailVec;
public:
SkipList(int totalLevels);
void append(T& data, int level);
void pop(int level);
void pop();
T front(int level);
int size();
void flush();
list<pair<T, int>> dump();
list<pair<T, int>> dump(int level);
};
template <typename T>
SkipList<T>::SkipList(int totalLevels): mHeadVec(totalLevels, mMainList.end()),
mTailVec(totalLevels, mMainList.end()) {}
template <typename T>
void SkipList<T>::append(T& data, int level) {
if ( level < 0 || level >= mHeadVec.size()) {
return;
}
SkipNode<T> node(level, data);
node.mNextInLevel = mMainList.end();
mMainList.push_back(node);
auto iter = --mMainList.end();
if (mHeadVec[level] == mMainList.end()) {
mHeadVec[level] = iter;
} else {
(*mTailVec[level]).mNextInLevel = iter;
}
mTailVec[level] = iter;
}
template <typename T>
void SkipList<T>::pop(int level) {
if (mHeadVec[level] == mMainList.end()) {
return;
}
if ((*mHeadVec[level]).mNextInLevel == mMainList.end()) {
mTailVec[level] = mMainList.end();
}
auto tmp_iter = (*mHeadVec[level]).mNextInLevel;
mMainList.erase(mHeadVec[level]);
mHeadVec[level] = tmp_iter;
}
template <typename T>
void SkipList<T>::pop() {
pop(mMainList.front().mLevel);
}
template <typename T>
T SkipList<T>::front(int level) {
return (*mHeadVec[level]).mData;
}
template <typename T>
int SkipList<T>::size() {
return mMainList.size();
}
template <typename T>
void SkipList<T>::flush() {
mMainList.clear();
for (int i = 0; i < mHeadVec.size(); i++) {
mHeadVec[i] = mMainList.end();
mTailVec[i] = mMainList.end();
}
}
template <typename T>
list<pair<T, int>> SkipList<T>::dump() {
list<pair<T, int>> li;
for_each(mMainList.begin(), mMainList.end(), [&](SkipNode<T> &item) {
li.push_back(make_pair(item.mData, item.mLevel));
});
return li;
}
template <typename T>
list<pair<T, int>> SkipList<T>::dump(int level) {
list<pair<T, int>> li;
auto head = mHeadVec[level];
while (head != mMainList.end()) {
li.push_back(make_pair((*head).mData, (*head).mLevel));
head = (*head).mNextInLevel;
}
return li;
}
}
#endif

92
gps/utils/configure.ac Normal file
View file

@ -0,0 +1,92 @@
# configure.ac -- Autoconf script for gps gps-utils
#
# Process this file with autoconf to produce a configure script
# Requires autoconf tool later than 2.61
AC_PREREQ(2.61)
# Initialize the gps gps-utils package version 1.0.0
AC_INIT([gps-utils],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
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([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_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 \
gps-utils.pc
])
AC_OUTPUT

10
gps/utils/gps-utils.pc.in Normal file
View file

@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: gps-utils
Description: QTI GPS Location utils
Version: @VERSION
Libs: -L${libdir} -lgps_utils
Cflags: -I${includedir}/gps-utils

114
gps/utils/gps_extended.h Normal file
View file

@ -0,0 +1,114 @@
/* Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GPS_EXTENDED_H
#define GPS_EXTENDED_H
/**
* @file
* @brief C++ declarations for GPS types
*/
#include <gps_extended_c.h>
#if defined(USE_GLIB) || defined(OFF_TARGET)
#include <string.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct LocPosMode
{
LocPositionMode mode;
LocGpsPositionRecurrence recurrence;
uint32_t min_interval;
uint32_t preferred_accuracy;
uint32_t preferred_time;
bool share_position;
char credentials[14];
char provider[8];
GnssPowerMode powerMode;
uint32_t timeBetweenMeasurements;
LocPosMode(LocPositionMode m, LocGpsPositionRecurrence recr,
uint32_t gap, uint32_t accu, uint32_t time,
bool sp, const char* cred, const char* prov,
GnssPowerMode pMode = GNSS_POWER_MODE_INVALID,
uint32_t tbm = 0) :
mode(m), recurrence(recr),
min_interval(gap < GPS_MIN_POSSIBLE_FIX_INTERVAL_MS ?
GPS_MIN_POSSIBLE_FIX_INTERVAL_MS : gap),
preferred_accuracy(accu), preferred_time(time),
share_position(sp), powerMode(pMode),
timeBetweenMeasurements(tbm) {
memset(credentials, 0, sizeof(credentials));
memset(provider, 0, sizeof(provider));
if (NULL != cred) {
memcpy(credentials, cred, sizeof(credentials)-1);
}
if (NULL != prov) {
memcpy(provider, prov, sizeof(provider)-1);
}
}
inline LocPosMode() :
mode(LOC_POSITION_MODE_MS_BASED),
recurrence(LOC_GPS_POSITION_RECURRENCE_PERIODIC),
min_interval(GPS_DEFAULT_FIX_INTERVAL_MS),
preferred_accuracy(50), preferred_time(120000),
share_position(true), powerMode(GNSS_POWER_MODE_INVALID),
timeBetweenMeasurements(GPS_DEFAULT_FIX_INTERVAL_MS) {
memset(credentials, 0, sizeof(credentials));
memset(provider, 0, sizeof(provider));
}
inline bool equals(const LocPosMode &anotherMode) const
{
return anotherMode.mode == mode &&
anotherMode.recurrence == recurrence &&
anotherMode.min_interval == min_interval &&
anotherMode.preferred_accuracy == preferred_accuracy &&
anotherMode.preferred_time == preferred_time &&
anotherMode.powerMode == powerMode &&
anotherMode.timeBetweenMeasurements == timeBetweenMeasurements &&
!strncmp(anotherMode.credentials, credentials, sizeof(credentials)-1) &&
!strncmp(anotherMode.provider, provider, sizeof(provider)-1);
}
void logv() const;
};
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* GPS_EXTENDED_H */

2429
gps/utils/gps_extended_c.h Normal file

File diff suppressed because it is too large Load diff

325
gps/utils/linked_list.c Normal file
View file

@ -0,0 +1,325 @@
/* Copyright (c) 2011, 2014, 2017 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.
*/
#define LOG_TAG "LocSvc_utils_ll"
#include "linked_list.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <loc_pla.h>
#include <log_util.h>
typedef struct list_element {
struct list_element* next;
struct list_element* prev;
void* data_ptr;
void (*dealloc_func)(void*);
}list_element;
typedef struct list_state {
list_element* p_head;
list_element* p_tail;
} list_state;
/* ----------------------- END INTERNAL FUNCTIONS ---------------------------------------- */
/*===========================================================================
FUNCTION: linked_list_init
===========================================================================*/
linked_list_err_type linked_list_init(void** list_data)
{
if( list_data == NULL )
{
LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__);
return eLINKED_LIST_INVALID_PARAMETER;
}
list_state* tmp_list;
tmp_list = (list_state*)calloc(1, sizeof(list_state));
if( tmp_list == NULL )
{
LOC_LOGE("%s: Unable to allocate space for list!\n", __FUNCTION__);
return eLINKED_LIST_FAILURE_GENERAL;
}
tmp_list->p_head = NULL;
tmp_list->p_tail = NULL;
*list_data = tmp_list;
return eLINKED_LIST_SUCCESS;
}
/*===========================================================================
FUNCTION: linked_list_destroy
===========================================================================*/
linked_list_err_type linked_list_destroy(void** list_data)
{
if( list_data == NULL )
{
LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__);
return eLINKED_LIST_INVALID_HANDLE;
}
list_state* p_list = (list_state*)*list_data;
linked_list_flush(p_list);
free(*list_data);
*list_data = NULL;
return eLINKED_LIST_SUCCESS;
}
/*===========================================================================
FUNCTION: linked_list_add
===========================================================================*/
linked_list_err_type linked_list_add(void* list_data, void *data_obj, void (*dealloc)(void*))
{
if( list_data == NULL )
{
LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__);
return eLINKED_LIST_INVALID_HANDLE;
}
if( data_obj == NULL )
{
LOC_LOGE("%s: Invalid input parameter!\n", __FUNCTION__);
return eLINKED_LIST_INVALID_PARAMETER;
}
list_state* p_list = (list_state*)list_data;
list_element* elem = (list_element*)malloc(sizeof(list_element));
if( elem == NULL )
{
LOC_LOGE("%s: Memory allocation failed\n", __FUNCTION__);
return eLINKED_LIST_FAILURE_GENERAL;
}
/* Copy data to newly created element */
elem->data_ptr = data_obj;
elem->next = NULL;
elem->prev = NULL;
elem->dealloc_func = dealloc;
/* Replace head element */
list_element* tmp = p_list->p_head;
p_list->p_head = elem;
/* Point next to the previous head element */
p_list->p_head->next = tmp;
if( tmp != NULL )
{
tmp->prev = p_list->p_head;
}
else
{
p_list->p_tail = p_list->p_head;
}
return eLINKED_LIST_SUCCESS;
}
/*===========================================================================
FUNCTION: linked_list_remove
===========================================================================*/
linked_list_err_type linked_list_remove(void* list_data, void **data_obj)
{
if( list_data == NULL )
{
LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__);
return eLINKED_LIST_INVALID_HANDLE;
}
if( data_obj == NULL )
{
LOC_LOGE("%s: Invalid input parameter!\n", __FUNCTION__);
return eLINKED_LIST_INVALID_PARAMETER;
}
list_state* p_list = (list_state*)list_data;
if( p_list->p_tail == NULL )
{
return eLINKED_LIST_UNAVAILABLE_RESOURCE;
}
list_element* tmp = p_list->p_tail;
/* Replace tail element */
p_list->p_tail = tmp->prev;
if( p_list->p_tail != NULL )
{
p_list->p_tail->next = NULL;
}
else
{
p_list->p_head = p_list->p_tail;
}
/* Copy data to output param */
*data_obj = tmp->data_ptr;
/* Free allocated list element */
free(tmp);
return eLINKED_LIST_SUCCESS;
}
/*===========================================================================
FUNCTION: linked_list_empty
===========================================================================*/
int linked_list_empty(void* list_data)
{
if( list_data == NULL )
{
LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__);
return (int)eLINKED_LIST_INVALID_HANDLE;
}
else
{
list_state* p_list = (list_state*)list_data;
return p_list->p_head == NULL ? 1 : 0;
}
}
/*===========================================================================
FUNCTION: linked_list_flush
===========================================================================*/
linked_list_err_type linked_list_flush(void* list_data)
{
if( list_data == NULL )
{
LOC_LOGE("%s: Invalid list parameter!\n", __FUNCTION__);
return eLINKED_LIST_INVALID_HANDLE;
}
list_state* p_list = (list_state*)list_data;
/* Remove all dynamically allocated elements */
while( p_list->p_head != NULL )
{
list_element* tmp = p_list->p_head->next;
/* Free data pointer if told to do so. */
if( p_list->p_head->dealloc_func != NULL )
{
p_list->p_head->dealloc_func(p_list->p_head->data_ptr);
}
/* Free list element */
free(p_list->p_head);
p_list->p_head = tmp;
}
p_list->p_tail = NULL;
return eLINKED_LIST_SUCCESS;
}
/*===========================================================================
FUNCTION: linked_list_search
===========================================================================*/
linked_list_err_type linked_list_search(void* list_data, void **data_p,
bool (*equal)(void* data_0, void* data),
void* data_0, bool rm_if_found)
{
if( list_data == NULL || NULL == equal )
{
LOC_LOGE("%s: Invalid list parameter! list_data %p equal %p\n",
__FUNCTION__, list_data, equal);
return eLINKED_LIST_INVALID_HANDLE;
}
list_state* p_list = (list_state*)list_data;
if( p_list->p_tail == NULL )
{
return eLINKED_LIST_UNAVAILABLE_RESOURCE;
}
list_element* tmp = p_list->p_head;
if (NULL != data_p) {
*data_p = NULL;
}
while (NULL != tmp) {
if ((*equal)(data_0, tmp->data_ptr)) {
if (NULL != data_p) {
*data_p = tmp->data_ptr;
}
if (rm_if_found) {
if (NULL == tmp->prev) {
p_list->p_head = tmp->next;
} else {
tmp->prev->next = tmp->next;
}
if (NULL == tmp->next) {
p_list->p_tail = tmp->prev;
} else {
tmp->next->prev = tmp->prev;
}
tmp->prev = tmp->next = NULL;
// dealloc data if it is not copied out && caller
// has given us a dealloc function pointer.
if (NULL == data_p && NULL != tmp->dealloc_func) {
tmp->dealloc_func(tmp->data_ptr);
}
free(tmp);
}
tmp = NULL;
} else {
tmp = tmp->next;
}
}
return eLINKED_LIST_SUCCESS;
}

219
gps/utils/linked_list.h Normal file
View file

@ -0,0 +1,219 @@
/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __LINKED_LIST_H__
#define __LINKED_LIST_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <stdbool.h>
#include <stdlib.h>
/** Linked List Return Codes */
typedef enum
{
eLINKED_LIST_SUCCESS = 0,
/**< Request was successful. */
eLINKED_LIST_FAILURE_GENERAL = -1,
/**< Failed because of a general failure. */
eLINKED_LIST_INVALID_PARAMETER = -2,
/**< Failed because the request contained invalid parameters. */
eLINKED_LIST_INVALID_HANDLE = -3,
/**< Failed because an invalid handle was specified. */
eLINKED_LIST_UNAVAILABLE_RESOURCE = -4,
/**< Failed because an there were not enough resources. */
eLINKED_LIST_INSUFFICIENT_BUFFER = -5,
/**< Failed because an the supplied buffer was too small. */
eLINKED_LIST_EMPTY = -6
/**< Failed because list is empty. */
}linked_list_err_type;
/*===========================================================================
FUNCTION linked_list_init
DESCRIPTION
Initializes internal structures for linked list.
list_data: State of list to be initialized.
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
linked_list_err_type linked_list_init(void** list_data);
/*===========================================================================
FUNCTION linked_list_destroy
DESCRIPTION
Destroys internal structures for linked list.
p_list_data: State of list to be destroyed.
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
linked_list_err_type linked_list_destroy(void** list_data);
/*===========================================================================
FUNCTION linked_list_add
DESCRIPTION
Adds an element to the head of the linked list. The passed in data pointer
is not modified or freed. Passed in data_obj is expected to live throughout
the use of the linked_list (i.e. data is not allocated internally)
p_list_data: List to add data to the head of.
data_obj: Pointer to data to add into list
dealloc: Function used to deallocate memory for this element. Pass NULL
if you do not want data deallocated during a flush operation
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
linked_list_err_type linked_list_add(void* list_data, void *data_obj, void (*dealloc)(void*));
/*===========================================================================
FUNCTION linked_list_remove
DESCRIPTION
Retrieves data from the list tail. data_obj is the tail element from the list
passed in by linked_list_add.
p_list_data: List to remove the tail from.
data_obj: Pointer to data removed from list
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
linked_list_err_type linked_list_remove(void* list_data, void **data_obj);
/*===========================================================================
FUNCTION linked_list_empty
DESCRIPTION
Tells whether the list currently contains any elements
p_list_data: List to check if empty.
DEPENDENCIES
N/A
RETURN VALUE
0/FALSE : List contains elements
1/TRUE : List is Empty
Otherwise look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
int linked_list_empty(void* list_data);
/*===========================================================================
FUNCTION linked_list_flush
DESCRIPTION
Removes all elements from the list and deallocates them using the provided
dealloc function while adding elements.
p_list_data: List to remove all elements from.
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
linked_list_err_type linked_list_flush(void* list_data);
/*===========================================================================
FUNCTION linked_list_search
DESCRIPTION
Searches for an element in the linked list.
p_list_data: List handle.
data_p: to be stored with the data found; NUll if no match.
if data_p passed in as NULL, then no write to it.
equal: Function ptr takes in a list element, and returns
indication if this the one looking for.
data_0: The data being compared against.
rm_if_found: Should data be removed if found?
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
linked_list_err_type linked_list_search(void* list_data, void **data_p,
bool (*equal)(void* data_0, void* data),
void* data_0, bool rm_if_found);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __LINKED_LIST_H__ */

1140
gps/utils/loc_cfg.cpp Normal file

File diff suppressed because it is too large Load diff

167
gps/utils/loc_cfg.h Normal file
View file

@ -0,0 +1,167 @@
/* Copyright (c) 2011-2015, 2018, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_CFG_H
#define LOC_CFG_H
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#define LOC_MAX_PARAM_NAME 80
#define LOC_MAX_PARAM_STRING 172
#define LOC_MAX_PARAM_LINE (LOC_MAX_PARAM_NAME + LOC_MAX_PARAM_STRING)
#define LOC_FEATURE_MODE_DISABLED "DISABLED"
#define LOC_FEATURE_MODE_BASIC "BASIC"
#define LOC_FEATURE_MODE_PREMIUM "PREMIUM"
#define LOC_FEATURE_GTP_AP_CELL "gtp-ap-cell"
#define LOC_FEATURE_GTP_MODEM_CELL "gtp-modem-cell"
#define LOC_FEATURE_GTP_CELL_ENH "gtp-cell-enh"
#define LOC_FEATURE_GTP_WIFI "gtp-wifi"
#define LOC_FEATURE_GTP_WAA "gtp-waa"
#define LOC_FEATURE_SAP "sap"
#define LOC_PROCESS_MAX_NUM_GROUPS 20
#define LOC_PROCESS_MAX_NUM_ARGS 25
#define LOC_PROCESS_MAX_ARG_STR_LENGTH 32
#define UTIL_UPDATE_CONF(conf_data, len, config_table) \
loc_update_conf((conf_data), (len), (&config_table[0]), \
sizeof(config_table) / sizeof(config_table[0]))
#define UTIL_READ_CONF_DEFAULT(filename) \
loc_read_conf((filename), NULL, 0);
#define UTIL_READ_CONF(filename, config_table) \
loc_read_conf((filename), (&config_table[0]), sizeof(config_table) / sizeof(config_table[0]))
#define UTIL_READ_CONF_LONG(filename, config_table, rec_len) \
loc_read_conf_long((filename), (&config_table[0]), \
sizeof(config_table) / sizeof(config_table[0]), (rec_len))
/*=============================================================================
*
* MODULE TYPE DECLARATION
*
*============================================================================*/
typedef struct
{
const char *param_name;
void *param_ptr; /* for string type, buf size need to be LOC_MAX_PARAM_STRING */
uint8_t *param_set; /* indicate value set by config file */
char param_type; /* 'n' for number,
's' for string, NOTE: buf size need to be LOC_MAX_PARAM_STRING
'f' for double */
} loc_param_s_type;
typedef enum {
ENABLED,
RUNNING,
DISABLED,
DISABLED_FROM_CONF,
DISABLED_VIA_VENDOR_ENHANCED_CHECK
} loc_process_e_status;
typedef struct {
loc_process_e_status proc_status;
pid_t proc_id;
char name[2][LOC_MAX_PARAM_STRING];
gid_t group_list[LOC_PROCESS_MAX_NUM_GROUPS];
unsigned char num_groups;
char args[LOC_PROCESS_MAX_NUM_ARGS][LOC_PROCESS_MAX_ARG_STR_LENGTH];
char argumentString[LOC_MAX_PARAM_STRING];
} loc_process_info_s_type;
/*=============================================================================
*
* MODULE EXTERNAL DATA
*
*============================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
/*=============================================================================
*
* MODULE EXPORTED FUNCTIONS
*
*============================================================================*/
bool isVendorEnhanced();
void setVendorEnhanced(bool vendorEnhanced);
void loc_read_conf_long(const char* conf_file_name,
const loc_param_s_type* config_table,
uint32_t table_length, uint16_t string_len);
int loc_read_conf_r_long(FILE *conf_fp, const loc_param_s_type* config_table,
uint32_t table_length, uint16_t string_len);
int loc_update_conf_long(const char* conf_data, int32_t length,
const loc_param_s_type* config_table, uint32_t table_length,
uint16_t string_len);
inline void loc_read_conf(const char* conf_file_name,
const loc_param_s_type* config_table, uint32_t table_length) {
loc_read_conf_long(conf_file_name, config_table, table_length, LOC_MAX_PARAM_STRING);
}
inline int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table,
uint32_t table_length) {
return (loc_read_conf_r_long(conf_fp, config_table, table_length, LOC_MAX_PARAM_STRING));
}
inline int loc_update_conf(const char* conf_data, int32_t length,
const loc_param_s_type* config_table, uint32_t table_length) {
return (loc_update_conf_long(
conf_data, length, config_table, table_length, LOC_MAX_PARAM_STRING));
}
// Below are the location conf file paths
extern const char LOC_PATH_GPS_CONF[];
extern const char LOC_PATH_IZAT_CONF[];
extern const char LOC_PATH_FLP_CONF[];
extern const char LOC_PATH_LOWI_CONF[];
extern const char LOC_PATH_SAP_CONF[];
extern const char LOC_PATH_APDR_CONF[];
extern const char LOC_PATH_XTWIFI_CONF[];
extern const char LOC_PATH_QUIPC_CONF[];
extern const char LOC_PATH_ANT_CORR[];
extern const char LOC_PATH_SLIM_CONF[];
extern const char LOC_PATH_VPE_CONF[];
int loc_read_process_conf(const char* conf_file_name, uint32_t * process_count_ptr,
loc_process_info_s_type** process_info_table_ptr);
int loc_get_datum_type();
#ifdef __cplusplus
}
#endif
#endif /* LOC_CFG_H */

2235
gps/utils/loc_gps.h Normal file

File diff suppressed because it is too large Load diff

282
gps/utils/loc_log.cpp Normal file
View file

@ -0,0 +1,282 @@
/* Copyright (c) 2011-2012, 2015, 2020, 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.
*
*/
#define LOG_NDEBUG 0
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include "log_util.h"
#include "loc_log.h"
#include "msg_q.h"
#include <loc_pla.h>
#include "LogBuffer.h"
#include <unordered_map>
#include <fstream>
#include <algorithm>
#include <string>
#include <cctype>
#define BUFFER_SIZE 120
#define LOG_TAG_LEVEL_CONF_FILE_PATH "/data/vendor/location/gps.prop"
// Logging Improvements
const char *loc_logger_boolStr[]={"False","True"};
const char VOID_RET[] = "None";
const char FROM_AFW[] = "===>";
const char TO_MODEM[] = "--->";
const char FROM_MODEM[] = "<---";
const char TO_AFW[] = "<===";
const char EXIT_TAG[] = "Exiting";
const char ENTRY_TAG[] = "Entering";
const char EXIT_ERROR_TAG[] = "Exiting with error";
int build_type_prop = BUILD_TYPE_PROP_NA;
const string gEmptyStr = "";
const string gUnknownStr = "UNKNOWN";
/* Logging Mechanism */
loc_logger_s_type loc_logger;
/* tag base logging control map*/
static std::unordered_map<std::string, uint8_t> tag_level_map;
static bool tag_map_inited = false;
/* returns the least signification bit that is set in the mask
Param
mask - bit mask.
clearTheBit - if true, mask gets modified upon return.
returns 0 if mask is 0.
*/
uint64_t loc_get_least_bit(uint64_t& mask, bool clearTheBit) {
uint64_t bit = 0;
if (mask > 0) {
uint64_t less1 = mask - 1;
bit = mask & ~(less1);
if (clearTheBit) {
mask &= less1;
}
}
return bit;
}
string loc_get_bit_defs(uint64_t mask, const NameValTbl& tbl) {
string out;
while (mask > 0) {
out += loc_get_name_from_tbl(tbl, loc_get_least_bit(mask));
if (mask > 0) {
out += " | ";
}
}
return out;
}
DECLARE_TBL(loc_msg_q_status) =
{
NAME_VAL( eMSG_Q_SUCCESS ),
NAME_VAL( eMSG_Q_FAILURE_GENERAL ),
NAME_VAL( eMSG_Q_INVALID_PARAMETER ),
NAME_VAL( eMSG_Q_INVALID_HANDLE ),
NAME_VAL( eMSG_Q_UNAVAILABLE_RESOURCE ),
NAME_VAL( eMSG_Q_INSUFFICIENT_BUFFER )
};
/* Find msg_q status name */
const char* loc_get_msg_q_status(int status)
{
return loc_get_name_from_val(loc_msg_q_status_tbl, (int64_t) status);
}
//Target names
DECLARE_TBL(target_name) =
{
NAME_VAL(GNSS_NONE),
NAME_VAL(GNSS_MSM),
NAME_VAL(GNSS_GSS),
NAME_VAL(GNSS_MDM),
NAME_VAL(GNSS_AUTO),
NAME_VAL(GNSS_UNKNOWN)
};
/*===========================================================================
FUNCTION loc_get_target_name
DESCRIPTION
Returns pointer to a string that contains name of the target
XX:XX:XX.000\0
RETURN VALUE
The target name string
===========================================================================*/
const char *loc_get_target_name(unsigned int target)
{
int64_t index = 0;
static char ret[BUFFER_SIZE];
snprintf(ret, sizeof(ret), " %s with%s SSC",
loc_get_name_from_val(target_name_tbl, getTargetGnssType(target)),
((target & HAS_SSC) == HAS_SSC) ? gEmptyStr.c_str() : "out");
return ret;
}
/*===========================================================================
FUNCTION loc_get_time
DESCRIPTION
Logs a callback event header.
The pointer time_string should point to a buffer of at least 13 bytes:
XX:XX:XX.000\0
RETURN VALUE
The time string
===========================================================================*/
char *loc_get_time(char *time_string, size_t buf_size)
{
struct timeval now; /* sec and usec */
struct tm now_tm; /* broken-down time */
char hms_string[80]; /* HH:MM:SS */
gettimeofday(&now, NULL);
localtime_r(&now.tv_sec, &now_tm);
strftime(hms_string, sizeof hms_string, "%H:%M:%S", &now_tm);
snprintf(time_string, buf_size, "%s.%03d", hms_string, (int) (now.tv_usec / 1000));
return time_string;
}
/*===========================================================================
FUNCTION get_timestamp
DESCRIPTION
Generates a timestamp using the current system time
DEPENDENCIES
N/A
RETURN VALUE
Char pointer to the parameter str
SIDE EFFECTS
N/A
===========================================================================*/
char * get_timestamp(char *str, unsigned long buf_size)
{
struct timeval tv;
struct timezone tz;
int hh, mm, ss;
gettimeofday(&tv, &tz);
hh = tv.tv_sec/3600%24;
mm = (tv.tv_sec%3600)/60;
ss = tv.tv_sec%60;
snprintf(str, buf_size, "%02d:%02d:%02d.%06ld", hh, mm, ss, tv.tv_usec);
return str;
}
/*===========================================================================
FUNCTION log_buffer_insert
DESCRIPTION
Insert a log sentence with specific level to the log buffer.
RETURN VALUE
N/A
===========================================================================*/
void log_buffer_insert(char *str, unsigned long buf_size, int level)
{
timespec tv;
clock_gettime(CLOCK_BOOTTIME, &tv);
uint64_t elapsedTime = (uint64_t)tv.tv_sec + (uint64_t)tv.tv_nsec/1000000000;
string ss = str;
loc_util::LogBuffer::getInstance()->append(ss, level, elapsedTime);
}
void log_tag_level_map_init()
{
if (tag_map_inited) {
return;
}
std::string filename = LOG_TAG_LEVEL_CONF_FILE_PATH;
std::ifstream s(filename);
if (!s.is_open()) {
ALOGE("cannot open file:%s", LOG_TAG_LEVEL_CONF_FILE_PATH);
} else {
std::string line;
while (std::getline(s, line)) {
line.erase(std::remove(line.begin(), line.end(), ' '), line.end());
int pos = line.find('=');
if (pos <= 0 || pos >= (line.size() - 1)) {
ALOGE("wrong format in gps.prop");
continue;
}
std::string tag = line.substr(0, pos);
std::string level = line.substr(pos+1, 1);
if (!std::isdigit(*(level.begin()))) {
ALOGE("wrong format in gps.prop");
continue;
}
tag_level_map[tag] = (uint8_t)std::stoul(level);
}
}
tag_map_inited = true;
}
int get_tag_log_level(const char* tag)
{
if (!tag_map_inited) {
return -1;
}
// in case LOG_TAG isn't defined in a source file, use the global log level
if (tag == NULL) {
return loc_logger.DEBUG_LEVEL;
}
int log_level;
auto search = tag_level_map.find(std::string(tag));
if (tag_level_map.end() != search) {
log_level = search->second;
} else {
log_level = loc_logger.DEBUG_LEVEL;
}
return log_level;
}

122
gps/utils/loc_log.h Normal file
View file

@ -0,0 +1,122 @@
/* Copyright (c) 2011-2012, 2015, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_LOG_H
#define LOC_LOG_H
#include <ctype.h>
#include <stdlib.h>
#include <unordered_map>
#include <string>
#include "loc_target.h"
#include "loc_misc_utils.h"
using std::string;
using std::unordered_map;
typedef unordered_map<int64_t, string> NameValTbl;
#define NAME_VAL(x) {x, "" #x ""}
#define DECLARE_TBL(T) static const NameValTbl T##_tbl
extern const string gEmptyStr;
extern const string gUnknownStr;
#define CHECK_MASK(type, value, mask_var, mask) \
(((mask_var) & (mask)) ? (type) (value) : (type) (-1))
#define LOC_TABLE_SIZE(table) (sizeof(table)/sizeof((table)[0]))
#define FIELDVAL_DEC(field) \
loc_put_tag_val(#field, to_string(field))
#define FIELDVAL_DEC_ARR(field) \
loc_put_tag_val(#field, \
loc_parenthesize(loc_prim_arr_to_string(field, \
sizeof(field)/sizeof(field[0]))))
#define FIELDVAL_HEX(field) \
loc_put_tag_val(#field, to_string_hex(field))
#define FIELDVAL_HEX_ARR(field) \
loc_put_tag_val(#field, \
loc_parenthesize(loc_prim_arr_to_string(field, \
sizeof(field)/sizeof(field[0]), \
false)))
#define FIELDVAL_ENUM(field, tbl) \
loc_put_tag_val(#field, \
loc_get_name_from_tbl(tbl, field, gUnknownStr))
#define FIELDVAL_MASK(field, tbl) \
loc_put_tag_val(#field, \
to_string_hex((uint64_t)field) + " " + \
loc_parenthesize(loc_get_bit_defs(field, tbl)))
/* get from a table of strings with index */
/* tbl - map of <int, string> entries
key - key to the matching entry
defalt - default pointer in case of incorrect parameters
*/
inline static const string& loc_get_name_from_tbl(const NameValTbl& tbl, int64_t key,
const string& defalt = gEmptyStr) {
auto item = tbl.find(key);
if (item != tbl.end()) {
return item->second;
} else {
return defalt;
}
}
/* puts to string formatted "TAG: VAL" with option ending string, default to newline */
inline string loc_put_tag_val(const string& tag, const string& val, const string& eol = "\n") {
return tag + ": " + val + eol;
}
inline string loc_parenthesize(const string& str) {
return "(" + str + ")";
}
/* Get names from value */
inline const char* loc_get_name_from_val(const NameValTbl& table, int64_t value) {
return loc_get_name_from_tbl(table, value, gUnknownStr).c_str();
}
inline const char* log_succ_fail_string(int is_succ) {
return is_succ? "successful" : "failed";
}
/* prints mask into a string with bit definitions from tbl */
/* mask - bit mask, to be expanded into " BIT_NAMEx | BIT_NAMEy ... "
tbl - a table with defs for each bit, defined as <bit, name> entries
{{bit0, "BIT0_NAME"}, {bit1, "BIT1_NAME"}, .... {bitn, "BITn_NAME"} }
entries - number of strings in the table
*/
string loc_get_bit_defs(uint64_t mask, const NameValTbl& tbl);
uint64_t loc_get_least_bit(uint64_t& mask, bool clearThebit = true);
const char* loc_get_msg_q_status(int status);
const char* loc_get_target_name(unsigned int target);
char *loc_get_time(char *time_string, size_t buf_size);
#endif /* LOC_LOG_H */

View file

@ -0,0 +1,351 @@
/* Copyright (c) 2014, 2020 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.
*
*/
#define LOG_NDEBUG 0
#define LOG_TAG "LocSvc_misc_utils"
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <dlfcn.h>
#include <math.h>
#include <log_util.h>
#include <loc_misc_utils.h>
#include <ctype.h>
#include <fcntl.h>
#include <inttypes.h>
#ifndef MSEC_IN_ONE_SEC
#define MSEC_IN_ONE_SEC 1000ULL
#endif
#define GET_MSEC_FROM_TS(ts) ((ts.tv_sec * MSEC_IN_ONE_SEC) + (ts.tv_nsec + 500000)/1000000)
int loc_util_split_string(char *raw_string, char **split_strings_ptr,
int max_num_substrings, char delimiter)
{
int raw_string_index=0;
int num_split_strings=0;
unsigned char end_string=0;
int raw_string_length=0;
if(!raw_string || !split_strings_ptr) {
LOC_LOGE("%s:%d]: NULL parameters", __func__, __LINE__);
num_split_strings = -1;
goto err;
}
LOC_LOGD("%s:%d]: raw string: %s\n", __func__, __LINE__, raw_string);
raw_string_length = strlen(raw_string) + 1;
split_strings_ptr[num_split_strings] = &raw_string[raw_string_index];
for(raw_string_index=0; raw_string_index < raw_string_length; raw_string_index++) {
if(raw_string[raw_string_index] == '\0')
end_string=1;
if((raw_string[raw_string_index] == delimiter) || end_string) {
raw_string[raw_string_index] = '\0';
if (num_split_strings < max_num_substrings) {
LOC_LOGD("%s:%d]: split string: %s\n",
__func__, __LINE__, split_strings_ptr[num_split_strings]);
}
num_split_strings++;
if(((raw_string_index + 1) < raw_string_length) &&
(num_split_strings < max_num_substrings)) {
split_strings_ptr[num_split_strings] = &raw_string[raw_string_index+1];
}
else {
break;
}
}
if(end_string)
break;
}
err:
LOC_LOGD("%s:%d]: num_split_strings: %d\n", __func__, __LINE__, num_split_strings);
return num_split_strings;
}
void loc_util_trim_space(char *org_string)
{
char *scan_ptr, *write_ptr;
char *first_nonspace = NULL, *last_nonspace = NULL;
if(org_string == NULL) {
LOC_LOGE("%s:%d]: NULL parameter", __func__, __LINE__);
goto err;
}
scan_ptr = write_ptr = org_string;
while (*scan_ptr) {
//Find the first non-space character
if ( !isspace(*scan_ptr) && first_nonspace == NULL) {
first_nonspace = scan_ptr;
}
//Once the first non-space character is found in the
//above check, keep shifting the characters to the left
//to replace the spaces
if (first_nonspace != NULL) {
*(write_ptr++) = *scan_ptr;
//Keep track of which was the last non-space character
//encountered
//last_nonspace will not be updated in the case where
//the string ends with spaces
if ( !isspace(*scan_ptr)) {
last_nonspace = write_ptr;
}
}
scan_ptr++;
}
//Add NULL terminator after the last non-space character
if (last_nonspace) { *last_nonspace = '\0'; }
err:
return;
}
inline void logDlError(const char* failedCall) {
const char * err = dlerror();
LOC_LOGe("%s error: %s", failedCall, (nullptr == err) ? "unknown" : err);
}
void* dlGetSymFromLib(void*& libHandle, const char* libName, const char* symName)
{
void* sym = nullptr;
if ((nullptr != libHandle || nullptr != libName) && nullptr != symName) {
if (nullptr == libHandle) {
libHandle = dlopen(libName, RTLD_NOW);
if (nullptr == libHandle) {
logDlError("dlopen");
}
}
// NOT else, as libHandle gets assigned 5 line above
if (nullptr != libHandle) {
sym = dlsym(libHandle, symName);
if (nullptr == sym) {
logDlError("dlsym");
}
}
} else {
LOC_LOGe("Either libHandle (%p) or libName (%p) must not be null; "
"symName (%p) can not be null.", libHandle, libName, symName);
}
return sym;
}
uint64_t getQTimerTickCount()
{
uint64_t qTimerCount = 0;
#if __aarch64__
asm volatile("mrs %0, cntvct_el0" : "=r" (qTimerCount));
#elif defined (__i386__) || defined (__x86_64__)
/* Qtimer not supported in x86 architecture */
qTimerCount = 0;
#else
asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (qTimerCount));
#endif
return qTimerCount;
}
uint64_t getQTimerDeltaNanos()
{
char qtimer_val_string[100];
char *temp;
uint64_t local_qtimer = 0, remote_qtimer = 0;
int mdm_fd = -1, wlan_fd = -1, ret = 0;
uint64_t delta = 0;
memset(qtimer_val_string, '\0', sizeof(qtimer_val_string));
char devNode[] = "/sys/bus/mhi/devices/0306_00.01.00/time_us";
for (; devNode[27] < 3 && mdm_fd < 0; devNode[27]++) {
mdm_fd = ::open(devNode, O_RDONLY);
if (mdm_fd < 0) {
LOC_LOGe("MDM open file: %s error: %s", devNode, strerror(errno));
}
}
if (mdm_fd > 0) {
ret = read(mdm_fd, qtimer_val_string, sizeof(qtimer_val_string)-1);
::close(mdm_fd);
if (ret < 0) {
LOC_LOGe("MDM read time_us file error: %s", strerror(errno));
} else {
temp = qtimer_val_string;
temp = strchr(temp, ':');
temp = temp + 2;
local_qtimer = atoll(temp);
temp = strchr(temp, ':');
temp = temp + 2;
remote_qtimer = atoll(temp);
if (local_qtimer >= remote_qtimer) {
delta = (local_qtimer - remote_qtimer) * 1000;
}
LOC_LOGv("qtimer values in microseconds: local:%" PRIi64 " remote:%" PRIi64 ""
" delta in nanoseconds:%" PRIi64 "",
local_qtimer, remote_qtimer, delta);
}
}
return delta;
}
uint64_t getQTimerFreq()
{
#if __aarch64__
uint64_t val = 0;
asm volatile("mrs %0, cntfrq_el0" : "=r" (val));
#elif defined (__i386__) || defined (__x86_64__)
/* Qtimer not supported in x86 architecture */
uint64_t val = 0;
#else
uint32_t val = 0;
asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
#endif
return val;
}
uint64_t getBootTimeMilliSec()
{
struct timespec curTs;
clock_gettime(CLOCK_BOOTTIME, &curTs);
return (uint64_t)GET_MSEC_FROM_TS(curTs);
}
// Used for convert position/velocity from GSNS antenna based to VRP based
void Matrix_MxV(float a[3][3], float b[3], float c[3]) {
int i, j;
for (i=0; i<3; i++) {
c[i] = 0.0f;
for (j=0; j<3; j++)
c[i] += a[i][j] * b[j];
}
}
// Used for convert position/velocity from GNSS antenna based to VRP based
void Matrix_Skew(float a[3], float c[3][3]) {
c[0][0] = 0.0f;
c[0][1] = -a[2];
c[0][2] = a[1];
c[1][0] = a[2];
c[1][1] = 0.0f;
c[1][2] = -a[0];
c[2][0] = -a[1];
c[2][1] = a[0];
c[2][2] = 0.0f;
}
// Used for convert position/velocity from GNSS antenna based to VRP based
void Euler2Dcm(float euler[3], float dcm[3][3]) {
float cr = 0.0, sr = 0.0, cp = 0.0, sp = 0.0, ch = 0.0, sh = 0.0;
cr = cosf(euler[0]);
sr = sinf(euler[0]);
cp = cosf(euler[1]);
sp = sinf(euler[1]);
ch = cosf(euler[2]);
sh = sinf(euler[2]);
dcm[0][0] = cp * ch;
dcm[0][1] = (sp*sr*ch) - (cr*sh);
dcm[0][2] = (cr*sp*ch) + (sh*sr);
dcm[1][0] = cp * sh;
dcm[1][1] = (sr*sp*sh) + (cr*ch);
dcm[1][2] = (cr*sp*sh) - (sr*ch);
dcm[2][0] = -sp;
dcm[2][1] = sr * cp;
dcm[2][2] = cr * cp;
}
// Used for convert position from GSNS based to VRP based
// The converted position will be stored in the llaInfo parameter.
#define A6DOF_WGS_A (6378137.0f)
#define A6DOF_WGS_B (6335439.0f)
#define A6DOF_WGS_E2 (0.00669437999014f)
void loc_convert_lla_gnss_to_vrp(double lla[3], float rollPitchYaw[3],
float leverArm[3]) {
LOC_LOGv("lla: %f, %f, %f, lever arm: %f %f %f, "
"rollpitchyaw: %f %f %f",
lla[0], lla[1], lla[2],
leverArm[0], leverArm[1], leverArm[2],
rollPitchYaw[0], rollPitchYaw[1], rollPitchYaw[2]);
float cnb[3][3];
memset(cnb, 0, sizeof(cnb));
Euler2Dcm(rollPitchYaw, cnb);
float sl = sin(lla[0]);
float cl = cos(lla[0]);
float sf = 1.0f / (1.0f - A6DOF_WGS_E2 * sl* sl);
float sfr = sqrtf(sf);
float rn = A6DOF_WGS_B * sf * sfr + lla[2];
float re = A6DOF_WGS_A * sfr + lla[2];
float deltaNEU[3];
// gps_pos_lla = imu_pos_lla + Cbn*la_b .* [1/geo.Rn; 1/(geo.Re*geo.cL); -1];
Matrix_MxV(cnb, leverArm, deltaNEU);
// NED to lla conversion
lla[0] = lla[0] + deltaNEU[0] / rn;
lla[1] = lla[1] + deltaNEU[1] / (re * cl);
lla[2] = lla[2] + deltaNEU[2];
}
// Used for convert velocity from GSNS based to VRP based
// The converted velocity will be stored in the enuVelocity parameter.
void loc_convert_velocity_gnss_to_vrp(float enuVelocity[3], float rollPitchYaw[3],
float rollPitchYawRate[3], float leverArm[3]) {
LOC_LOGv("enu velocity: %f, %f, %f, lever arm: %f %f %f, roll pitch yaw: %f %f %f,"
"rollpitchyawRate: %f %f %f",
enuVelocity[0], enuVelocity[1], enuVelocity[2],
leverArm[0], leverArm[1], leverArm[2],
rollPitchYaw[0], rollPitchYaw[1], rollPitchYaw[2],
rollPitchYawRate[0], rollPitchYawRate[1], rollPitchYawRate[2]);
float cnb[3][3];
memset(cnb, 0, sizeof(cnb));
Euler2Dcm(rollPitchYaw, cnb);
float skewLA[3][3];
memset(skewLA, 0, sizeof(skewLA));
Matrix_Skew(leverArm, skewLA);
float tmp[3];
float deltaEnuVelocity[3];
memset(tmp, 0, sizeof(tmp));
memset(deltaEnuVelocity, 0, sizeof(deltaEnuVelocity));
Matrix_MxV(skewLA, rollPitchYawRate, tmp);
Matrix_MxV(cnb, tmp, deltaEnuVelocity);
enuVelocity[0] = enuVelocity[0] - deltaEnuVelocity[0];
enuVelocity[1] = enuVelocity[1] - deltaEnuVelocity[1];
enuVelocity[2] = enuVelocity[2] - deltaEnuVelocity[2];
}

321
gps/utils/loc_misc_utils.h Normal file
View file

@ -0,0 +1,321 @@
/* Copyright (c) 2014, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _LOC_MISC_UTILS_H_
#define _LOC_MISC_UTILS_H_
#include <stdint.h>
#include <ios>
#include <string>
#include <sstream>
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#include <stdint.h>
/*===========================================================================
FUNCTION loc_split_string
DESCRIPTION:
This function is used to split a delimiter separated string into
sub-strings. This function does not allocate new memory to store the split
strings. Instead, it places '\0' in places of delimiters and assings the
starting address of the substring within the raw string as the string address
The input raw_string no longer remains to be a collection of sub-strings
after this function is executed.
Please make a copy of the input string before calling this function if
necessary
PARAMETERS:
char *raw_string: is the original string with delimiter separated substrings
char **split_strings_ptr: is the arraw of pointers which will hold the addresses
of individual substrings
int max_num_substrings: is the maximum number of substrings that are expected
by the caller. The array of pointers in the above parameter
is usually this long
char delimiter: is the delimiter that separates the substrings. Examples: ' ', ';'
DEPENDENCIES
N/A
RETURN VALUE
int Number of split strings
SIDE EFFECTS
The input raw_string no longer remains a delimiter separated single string.
EXAMPLE
delimiter = ' ' //space
raw_string = "hello new user" //delimiter is space ' '
addresses = 0123456789abcd
split_strings_ptr[0] = &raw_string[0]; //split_strings_ptr[0] contains "hello"
split_strings_ptr[1] = &raw_string[6]; //split_strings_ptr[1] contains "new"
split_strings_ptr[2] = &raw_string[a]; //split_strings_ptr[2] contains "user"
===========================================================================*/
int loc_util_split_string(char *raw_string, char **split_strings_ptr, int max_num_substrings,
char delimiter);
/*===========================================================================
FUNCTION trim_space
DESCRIPTION
Removes leading and trailing spaces of the string
DEPENDENCIES
N/A
RETURN VALUE
None
SIDE EFFECTS
N/A
===========================================================================*/
void loc_util_trim_space(char *org_string);
/*===========================================================================
FUNCTION dlGetSymFromLib
DESCRIPTION
Handy function to get a pointer to a symbol from a library.
If libHandle is not null, it will be used as the handle to the library. In
that case libName wll not be used;
libHandle is an in / out parameter.
If libHandle is null, libName will be used to dlopen.
Either libHandle or libName must not be nullptr.
symName must not be null.
DEPENDENCIES
N/A
RETURN VALUE
pointer to symName. Could be nullptr if
Parameters are incorrect; or
libName can not be opened; or
symName can not be found.
SIDE EFFECTS
N/A
===========================================================================*/
void* dlGetSymFromLib(void*& libHandle, const char* libName, const char* symName);
/*===========================================================================
FUNCTION getQTimerTickCount
DESCRIPTION
This function is used to read the QTimer ticks count. This value is globally maintained and
must be the same across all processors on a target.
DEPENDENCIES
N/A
RETURN VALUE
uint64_t QTimer tick count
SIDE EFFECTS
N/A
===========================================================================*/
uint64_t getQTimerTickCount();
/*===========================================================================
FUNCTION getQTimerDeltaNanos
DESCRIPTION
This function is used to read the the difference in nanoseconds between
Qtimer on AP side and Qtimer on MP side for dual-SoC architectures such as Kona
DEPENDENCIES
N/A
RETURN VALUE
uint64_t QTimer difference in nanoseconds
SIDE EFFECTS
N/A
===========================================================================*/
uint64_t getQTimerDeltaNanos();
/*===========================================================================
FUNCTION getQTimerFreq
DESCRIPTION
This function is used to read the QTimer frequency in hz. This value is globally maintained and
must be the same across all processors on a target.
DEPENDENCIES
N/A
RETURN VALUE
uint64_t QTimer frequency
SIDE EFFECTS
N/A
===========================================================================*/
uint64_t getQTimerFreq();
/*===========================================================================
FUNCTION getBootTimeMilliSec
DESCRIPTION
This function is used to get boot time in milliseconds.
DEPENDENCIES
N/A
RETURN VALUE
uint64_t boot time in milliseconds
SIDE EFFECTS
N/A
===========================================================================*/
uint64_t getBootTimeMilliSec();
#ifdef __cplusplus
}
#endif
using std::hex;
using std::string;
using std::stringstream;
/*===========================================================================
FUNCTION to_string_hex
DESCRIPTION
This function works similar to std::to_string, but puts only in hex format.
DEPENDENCIES
N/A
RETURN VALUE
string, of input val in hex format
SIDE EFFECTS
N/A
===========================================================================*/
template <typename T>
string to_string_hex(T val) {
stringstream ss;
if (val < 0) {
val = -val;
ss << "-";
}
ss << hex << "0x" << val;
return ss.str();
}
/*===========================================================================
FUNCTION loc_prim_arr_to_string
DESCRIPTION
This function puts out primitive array in DEC or EHX format.
DEPENDENCIES
N/A
RETURN VALUE
string, space separated string of values in the input array, either
in decimal or hex format, depending on the value of decIfTrue
SIDE EFFECTS
N/A
===========================================================================*/
template <typename T>
static string loc_prim_arr_to_string(T* arr, uint32_t size, bool decIfTrue = true) {
stringstream ss;
for (uint32_t i = 0; i < size; i++) {
ss << (decIfTrue ? to_string(arr[i]) : to_string_hex(arr[i]));
if (i != size - 1) {
ss << " ";
}
}
return ss.str();
}
/*===========================================================================
FUNCTION qTimerTicksToNanos
DESCRIPTION
Transform from ticks to nanoseconds, clock is 19.2 MHz
so the formula would be qtimer(ns) = (ticks * 1000000000) / 19200000
or simplified qtimer(ns) = (ticks * 10000) / 192.
DEPENDENCIES
N/A
RETURN VALUE
Qtimer value in nanoseconds
SIDE EFFECTS
N/A
===========================================================================*/
inline uint64_t qTimerTicksToNanos(double qTimer) {
return (uint64_t((qTimer * double(10000ull)) / (double)192ull));
}
/*===========================================================================
FUNCTION loc_convert_lla_gnss_to_vrp
DESCRIPTION
This function converts lat/long/altitude from GNSS antenna based
to vehicle reference point based.
DEPENDENCIES
N/A
RETURN VALUE
The converted lat/long/altitude will be stored in the parameter of llaInfo.
SIDE EFFECTS
N/A
===========================================================================*/
void loc_convert_lla_gnss_to_vrp(double lla[3], float rollPitchYaw[3],
float leverArm[3]);
/*===========================================================================
FUNCTION loc_convert_velocity_gnss_to_vrp
DESCRIPTION
This function converts east/north/up velocity from GNSS antenna based
to vehicle reference point based.
DEPENDENCIES
N/A
RETURN VALUE
The converted east/north/up velocity will be stored in the parameter of
enuVelocity.
SIDE EFFECTS
N/A
===========================================================================*/
void loc_convert_velocity_gnss_to_vrp(float enuVelocity[3], float rollPitchYaw[3],
float rollPitchYawRate[3], float leverArm[3]);
#endif //_LOC_MISC_UTILS_H_

2347
gps/utils/loc_nmea.cpp Normal file

File diff suppressed because it is too large Load diff

95
gps/utils/loc_nmea.h Normal file
View file

@ -0,0 +1,95 @@
/* Copyright (c) 2012-2013, 2015-2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_ENG_NMEA_H
#define LOC_ENG_NMEA_H
#include <gps_extended.h>
#include <vector>
#include <string>
#define NMEA_SENTENCE_MAX_LENGTH 200
/** gnss datum type */
#define LOC_GNSS_DATUM_WGS84 0
#define LOC_GNSS_DATUM_PZ90 1
/* len of semi major axis of ref ellips*/
#define MAJA (6378137.0)
/* flattening coef of ref ellipsoid*/
#define FLAT (1.0/298.2572235630)
/* 1st eccentricity squared*/
#define ESQR (FLAT*(2.0 - FLAT))
/*1 minus eccentricity squared*/
#define OMES (1.0 - ESQR)
#define MILARCSEC2RAD (4.848136811095361e-09)
/*semi major axis */
#define C_PZ90A (6378136.0)
/*semi minor axis */
#define C_PZ90B (6356751.3618)
/* Transformation from WGS84 to PZ90
* Cx,Cy,Cz,Rs,Rx,Ry,Rz,C_SYS_A,C_SYS_B*/
const double DatumConstFromWGS84[9] =
{+0.003, +0.001, 0.000, (1.0+(0.000*1E-6)), (-0.019*MILARCSEC2RAD),
(+0.042*MILARCSEC2RAD), (-0.002*MILARCSEC2RAD), C_PZ90A, C_PZ90B};
/** Represents a LTP*/
typedef struct {
double lat;
double lon;
double alt;
} LocLla;
/** Represents a ECEF*/
typedef struct {
double X;
double Y;
double Z;
} LocEcef;
void loc_nmea_generate_sv(const GnssSvNotification &svNotify,
std::vector<std::string> &nmeaArraystr);
void loc_nmea_generate_pos(const UlpLocation &location,
const GpsLocationExtended &locationExtended,
const LocationSystemInfo &systemInfo,
unsigned char generate_nmea,
bool custom_gga_fix_quality,
std::vector<std::string> &nmeaArraystr,
int& indexOfGGA,
bool isTagBlockGroupingEnabled);
#define DEBUG_NMEA_MINSIZE 6
#define DEBUG_NMEA_MAXSIZE 4096
inline bool loc_nmea_is_debug(const char* nmea, int length) {
return ((nullptr != nmea) &&
(length >= DEBUG_NMEA_MINSIZE) && (length <= DEBUG_NMEA_MAXSIZE) &&
(nmea[0] == '$') && (nmea[1] == 'P') && (nmea[2] == 'Q') && (nmea[3] == 'W'));
}
#endif // LOC_ENG_NMEA_H

249
gps/utils/loc_target.cpp Normal file
View file

@ -0,0 +1,249 @@
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <log_util.h>
#include "loc_target.h"
#include "loc_log.h"
#include <loc_pla.h>
#define APQ8064_ID_1 "109"
#define APQ8064_ID_2 "153"
#define MPQ8064_ID_1 "130"
#define MSM8930_ID_1 "142"
#define MSM8930_ID_2 "116"
#define APQ8030_ID_1 "157"
#define APQ8074_ID_1 "184"
#define LINE_LEN 100
#define STR_LIQUID "Liquid"
#define STR_SURF "Surf"
#define STR_MTP "MTP"
#define STR_APQ "apq"
#define STR_SDC "sdc" // alternative string for APQ targets
#define STR_QCS "qcs" // string for Gen9 APQ targets
#define STR_MSM "msm"
#define STR_SDM "sdm" // alternative string for MSM targets
#define STR_APQ_NO_WGR "baseband_apq_nowgr"
#define STR_AUTO "auto"
#define IS_STR_END(c) ((c) == '\0' || (c) == '\n' || (c) == '\r')
#define LENGTH(s) (sizeof(s) - 1)
#define GPS_CHECK_NO_ERROR 0
#define GPS_CHECK_NO_GPS_HW 1
static unsigned int gTarget = (unsigned int)-1;
static int read_a_line(const char * file_path, char * line, int line_size)
{
FILE *fp;
int result = 0;
* line = '\0';
fp = fopen(file_path, "r" );
if( fp == NULL ) {
LOC_LOGE("open failed: %s: %s\n", file_path, strerror(errno));
result = -1;
} else {
int len;
fgets(line, line_size, fp);
len = strlen(line);
while ('\n' == line[len-1]) {
// If there is a new line at end of string, replace it with NULL
line[len-1] = '\0';
len--;
}
len = len < line_size - 1? len : line_size - 1;
line[len] = '\0';
LOC_LOGD("cat %s: %s", file_path, line);
fclose(fp);
}
return result;
}
/*The character array passed to this function should have length
of atleast PROPERTY_VALUE_MAX*/
void loc_get_target_baseband(char *baseband, int array_length)
{
if(baseband && (array_length >= PROPERTY_VALUE_MAX)) {
property_get("ro.baseband", baseband, "");
LOC_LOGD("%s:%d]: Baseband: %s\n", __func__, __LINE__, baseband);
}
else {
LOC_LOGE("%s:%d]: NULL parameter or array length less than PROPERTY_VALUE_MAX\n",
__func__, __LINE__);
}
}
/*The character array passed to this function should have length
of atleast PROPERTY_VALUE_MAX*/
void loc_get_platform_name(char *platform_name, int array_length)
{
if(platform_name && (array_length >= PROPERTY_VALUE_MAX)) {
property_get("ro.board.platform", platform_name, "");
LOC_LOGD("%s:%d]: Target name: %s\n", __func__, __LINE__, platform_name);
}
else {
LOC_LOGE("%s:%d]: Null parameter or array length less than PROPERTY_VALUE_MAX\n",
__func__, __LINE__);
}
}
/*The character array passed to this function should have length
of atleast PROPERTY_VALUE_MAX*/
void loc_get_auto_platform_name(char *platform_name, int array_length)
{
if(platform_name && (array_length >= PROPERTY_VALUE_MAX)) {
property_get("ro.hardware.type", platform_name, "");
LOC_LOGD("%s:%d]: Autoplatform name: %s\n", __func__, __LINE__, platform_name);
}
else {
LOC_LOGE("%s:%d]: Null parameter or array length less than PROPERTY_VALUE_MAX\n",
__func__, __LINE__);
}
}
/*Reads the property ro.config.low_ram to identify if this is a low ram target
Returns:
0 if not a low ram target
1 if this is a low ram target
*/
int loc_identify_low_ram_target()
{
int ret = 0;
char low_ram_target[PROPERTY_VALUE_MAX];
property_get("ro.config.low_ram", low_ram_target, "");
LOC_LOGd("low ram target: %s\n", low_ram_target);
return !(strncmp(low_ram_target, "true", PROPERTY_VALUE_MAX));
}
/*The character array passed to this function should have length
of atleast PROPERTY_VALUE_MAX*/
/* Reads the soc_id node and return the soc_id value */
void loc_get_device_soc_id(char *soc_id_value, int array_length)
{
static const char soc_id[] = "/sys/devices/soc0/soc_id";
static const char soc_id_dep[] = "/sys/devices/system/soc/soc0/id";
int return_val = 0;
if (soc_id_value && (array_length >= PROPERTY_VALUE_MAX)) {
if (!access(soc_id, F_OK)) {
return_val = read_a_line(soc_id, soc_id_value, array_length);
} else {
return_val = read_a_line(soc_id_dep, soc_id_value, array_length);
}
if (0 == return_val) {
LOC_LOGd("SOC Id value: %s\n", soc_id_value);
} else {
LOC_LOGe("Unable to read the soc_id value\n");
}
} else {
LOC_LOGe("Null parameter or array length less than PROPERTY_VALUE_MAX\n");
}
}
unsigned int loc_get_target(void)
{
if (gTarget != (unsigned int)-1)
return gTarget;
static const char hw_platform[] = "/sys/devices/soc0/hw_platform";
static const char hw_platform_dep[] =
"/sys/devices/system/soc/soc0/hw_platform";
static const char mdm[] = "/target"; // mdm target we are using
char rd_hw_platform[LINE_LEN];
char rd_id[LINE_LEN];
char rd_mdm[LINE_LEN];
char baseband[LINE_LEN];
char rd_auto_platform[LINE_LEN];
loc_get_target_baseband(baseband, sizeof(baseband));
if (!access(hw_platform, F_OK)) {
read_a_line(hw_platform, rd_hw_platform, LINE_LEN);
} else {
read_a_line(hw_platform_dep, rd_hw_platform, LINE_LEN);
}
// Get the soc-id for this device.
loc_get_device_soc_id(rd_id, sizeof(rd_id));
/*check automotive platform*/
loc_get_auto_platform_name(rd_auto_platform, sizeof(rd_auto_platform));
if( !memcmp(rd_auto_platform, STR_AUTO, LENGTH(STR_AUTO)) )
{
gTarget = TARGET_AUTO;
goto detected;
}
if( !memcmp(baseband, STR_APQ_NO_WGR, LENGTH(STR_APQ_NO_WGR)) ){
gTarget = TARGET_NO_GNSS;
goto detected;
}
if( !memcmp(baseband, STR_APQ, LENGTH(STR_APQ)) ||
!memcmp(baseband, STR_SDC, LENGTH(STR_SDC)) ||
!memcmp(baseband, STR_QCS, LENGTH(STR_QCS)) ) {
if( !memcmp(rd_id, MPQ8064_ID_1, LENGTH(MPQ8064_ID_1))
&& IS_STR_END(rd_id[LENGTH(MPQ8064_ID_1)]) )
gTarget = TARGET_NO_GNSS;
else
gTarget = TARGET_APQ_SA;
} else if (((!memcmp(rd_hw_platform, STR_LIQUID, LENGTH(STR_LIQUID))
&& IS_STR_END(rd_hw_platform[LENGTH(STR_LIQUID)])) ||
(!memcmp(rd_hw_platform, STR_SURF, LENGTH(STR_SURF))
&& IS_STR_END(rd_hw_platform[LENGTH(STR_SURF)])) ||
(!memcmp(rd_hw_platform, STR_MTP, LENGTH(STR_MTP))
&& IS_STR_END(rd_hw_platform[LENGTH(STR_MTP)]))) &&
!read_a_line( mdm, rd_mdm, LINE_LEN)) {
gTarget = TARGET_MDM;
} else if( (!memcmp(rd_id, MSM8930_ID_1, LENGTH(MSM8930_ID_1))
&& IS_STR_END(rd_id[LENGTH(MSM8930_ID_1)])) ||
(!memcmp(rd_id, MSM8930_ID_2, LENGTH(MSM8930_ID_2))
&& IS_STR_END(rd_id[LENGTH(MSM8930_ID_2)])) ) {
gTarget = TARGET_MSM_NO_SSC;
} else if ( !memcmp(baseband, STR_MSM, LENGTH(STR_MSM)) ||
!memcmp(baseband, STR_SDM, LENGTH(STR_SDM)) ) {
gTarget = TARGET_DEFAULT;
} else {
gTarget = TARGET_UNKNOWN;
}
detected:
LOC_LOGW("HAL: %s returned %d", __FUNCTION__, gTarget);
return gTarget;
}

82
gps/utils/loc_target.h Normal file
View file

@ -0,0 +1,82 @@
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef LOC_TARGET_H
#define LOC_TARGET_H
#define TARGET_SET(gnss,ssc) ( (gnss<<1)|ssc )
#define TARGET_DEFAULT TARGET_SET(GNSS_MSM, HAS_SSC)
#define TARGET_MDM TARGET_SET(GNSS_MDM, HAS_SSC)
#define TARGET_APQ_SA TARGET_SET(GNSS_GSS, NO_SSC)
#define TARGET_NO_GNSS TARGET_SET(GNSS_NONE, NO_SSC)
#define TARGET_MSM_NO_SSC TARGET_SET(GNSS_MSM, NO_SSC)
#define TARGET_AUTO TARGET_SET(GNSS_AUTO, NO_SSC)
#define TARGET_UNKNOWN TARGET_SET(GNSS_UNKNOWN, NO_SSC)
#define getTargetGnssType(target) (target>>1)
#ifdef __cplusplus
extern "C"
{
#endif
unsigned int loc_get_target(void);
/*The character array passed to this function should have length
of atleast PROPERTY_VALUE_MAX*/
void loc_get_target_baseband(char *baseband, int array_length);
/*The character array passed to this function should have length
of atleast PROPERTY_VALUE_MAX*/
void loc_get_platform_name(char *platform_name, int array_length);
/*The character array passed to this function should have length
of atleast PROPERTY_VALUE_MAX*/
void loc_get_auto_platform_name(char *platform_name, int array_length);
int loc_identify_low_ram_target();
/*The character array passed to this function should have length
of atleast PROPERTY_VALUE_MAX*/
void loc_get_device_soc_id(char *soc_id_value, int array_length);
/* Please remember to update 'target_name' in loc_log.cpp,
if do any changes to this enum. */
typedef enum {
GNSS_NONE = 0,
GNSS_MSM,
GNSS_GSS,
GNSS_MDM,
GNSS_AUTO,
GNSS_UNKNOWN
}GNSS_TARGET;
typedef enum {
NO_SSC = 0,
HAS_SSC
}SSC_TYPE;
#ifdef __cplusplus
}
#endif
#endif /*LOC_TARGET_H*/

74
gps/utils/loc_timer.h Normal file
View file

@ -0,0 +1,74 @@
/* Copyright (c) 2013,2015 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __LOC_DELAY_H__
#define __LOC_DELAY_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <stddef.h>
#include <stdint.h>
#include <loc_pla.h>
/*
user_data: client context pointer, passthrough. Originally received
from calling client when loc_timer_start() is called.
result: 0 if timer successfully timed out; else timer failed.
*/
typedef void (*loc_timer_callback)(void *user_data, int32_t result);
/*
delay_msec: timeout value for the timer.
cb_func: callback function pointer, implemented by client.
Can not be NULL.
user_data: client context pointer, passthrough. Will be
returned when loc_timer_callback() is called.
wakeOnExpire: true if to wake up CPU (if sleeping) upon timer
expiration and notify the client.
false if to wait until next time CPU wakes up (if
sleeping) and then notify the client.
Returns the handle, which can be used to stop the timer
NULL, if timer start fails (e.g. if cb_func is NULL).
*/
void* loc_timer_start(uint64_t delay_msec,
loc_timer_callback cb_func,
void *user_data,
bool wake_on_expire=false);
/*
handle becomes invalid upon the return of the callback
*/
void loc_timer_stop(void*& handle);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif //__LOC_DELAY_H__

291
gps/utils/log_util.h Normal file
View file

@ -0,0 +1,291 @@
/* Copyright (c) 2011-2014, 2020 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __LOG_UTIL_H__
#define __LOG_UTIL_H__
#include <stdbool.h>
#include <loc_pla.h>
#if defined (USE_ANDROID_LOGGING) || defined (ANDROID)
// Android and LE targets with logcat support
#include <utils/Log.h>
#include <unistd.h>
#include <sys/syscall.h>
#elif defined (USE_GLIB)
// LE targets with no logcat support
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/syscall.h>
#ifndef LOG_TAG
#define LOG_TAG "GPS_UTILS"
#endif /* LOG_TAG */
// LE targets with no logcat support
#if defined(FEATURE_EXTERNAL_AP) || defined(USE_SYSLOG_LOGGING)
#include <syslog.h>
#define ALOGE(...) syslog(LOG_ERR, "LOC_LOGE: " __VA_ARGS__);
#define ALOGW(...) syslog(LOG_WARNING, "LOC_LOGW: " __VA_ARGS__);
#define ALOGI(...) syslog(LOG_NOTICE, "LOC_LOGI: " __VA_ARGS__);
#define ALOGD(...) syslog(LOG_DEBUG, "LOC_LOGD: " __VA_ARGS__);
#define ALOGV(...) syslog(LOG_NOTICE, "LOC_LOGV: " __VA_ARGS__);
#else /* FEATURE_EXTERNAL_AP */
#define TS_PRINTF(format, x...) \
{ \
struct timeval tv; \
struct timezone tz; \
int hh, mm, ss; \
gettimeofday(&tv, &tz); \
hh = tv.tv_sec/3600%24; \
mm = (tv.tv_sec%3600)/60; \
ss = tv.tv_sec%60; \
fprintf(stdout,"%02d:%02d:%02d.%06ld]" format "\n", hh, mm, ss, tv.tv_usec, ##x); \
}
#define ALOGE(format, x...) TS_PRINTF("E/%s (%d): " format , LOG_TAG, getpid(), ##x)
#define ALOGW(format, x...) TS_PRINTF("W/%s (%d): " format , LOG_TAG, getpid(), ##x)
#define ALOGI(format, x...) TS_PRINTF("I/%s (%d): " format , LOG_TAG, getpid(), ##x)
#define ALOGD(format, x...) TS_PRINTF("D/%s (%d): " format , LOG_TAG, getpid(), ##x)
#define ALOGV(format, x...) TS_PRINTF("V/%s (%d): " format , LOG_TAG, getpid(), ##x)
#endif /* FEATURE_EXTERNAL_AP */
#endif /* #if defined (USE_ANDROID_LOGGING) || defined (ANDROID) */
#ifdef __cplusplus
extern "C"
{
#endif
/*=============================================================================
*
* LOC LOGGER TYPE DECLARATION
*
*============================================================================*/
/* LOC LOGGER */
typedef struct loc_logger_s
{
unsigned long DEBUG_LEVEL;
unsigned long TIMESTAMP;
bool LOG_BUFFER_ENABLE;
} loc_logger_s_type;
/*=============================================================================
*
* EXTERNAL DATA
*
*============================================================================*/
// Logging Improvements
extern const char *loc_logger_boolStr[];
extern loc_logger_s_type loc_logger;
extern const char *boolStr[];
extern const char VOID_RET[];
extern const char FROM_AFW[];
extern const char TO_MODEM[];
extern const char FROM_MODEM[];
extern const char TO_AFW[];
extern const char EXIT_TAG[];
extern const char ENTRY_TAG[];
extern const char EXIT_ERROR_TAG[];
#define BUILD_TYPE_PROP_NA 0
#define BUILD_TYPE_PROP_USER 1
#define BUILD_TYPE_PROP_USERDEBUG 2
#define BUILD_TYPE_PROP_INVALID 3
extern int build_type_prop;
/*=============================================================================
*
* MODULE EXPORTED FUNCTIONS
*
*============================================================================*/
inline void loc_logger_init(unsigned long debug, unsigned long timestamp)
{
loc_logger.DEBUG_LEVEL = debug;
if (BUILD_TYPE_PROP_NA == build_type_prop) {
char value[PROPERTY_VALUE_MAX] = "NA";
property_get("ro.build.type", value, "userdebug");
if (0 == strcmp(value, "user")) {
build_type_prop = BUILD_TYPE_PROP_USER;
} else if (0 == strcmp(value, "userdebug")) {
build_type_prop = BUILD_TYPE_PROP_USERDEBUG;
} else {
build_type_prop = BUILD_TYPE_PROP_INVALID;
}
}
if (BUILD_TYPE_PROP_USER == build_type_prop) {
// force user builds to 2 or less
if (loc_logger.DEBUG_LEVEL > 2) {
loc_logger.DEBUG_LEVEL = 2;
}
}
loc_logger.TIMESTAMP = timestamp;
}
inline void log_buffer_init(bool enabled) {
loc_logger.LOG_BUFFER_ENABLE = enabled;
}
extern void log_tag_level_map_init();
extern int get_tag_log_level(const char* tag);
extern char* get_timestamp(char* str, unsigned long buf_size);
extern void log_buffer_insert(char *str, unsigned long buf_size, int level);
/*=============================================================================
*
* LOGGING BUFFER MACROS
*
*============================================================================*/
#ifndef LOG_NDEBUG
#define LOG_NDEBUG 0
#endif
#define TOTAL_LOG_LEVELS 5
#define LOGGING_BUFFER_MAX_LEN 1024
#define IF_LOG_BUFFER_ENABLE if (loc_logger.LOG_BUFFER_ENABLE)
#define INSERT_BUFFER(flag, level, format, x...) \
{ \
IF_LOG_BUFFER_ENABLE { \
if (flag == 0) { \
char timestr[32]; \
get_timestamp(timestr, sizeof(timestr)); \
char log_str[LOGGING_BUFFER_MAX_LEN]; \
snprintf(log_str, LOGGING_BUFFER_MAX_LEN, "%s %d %ld %s :" format "\n", \
timestr, getpid(), syscall(SYS_gettid), LOG_TAG==NULL ? "": LOG_TAG, ##x);\
log_buffer_insert(log_str, sizeof(log_str), level); \
} \
} \
}
#ifndef DEBUG_DMN_LOC_API
/* LOGGING MACROS */
/*loc_logger.DEBUG_LEVEL is initialized to 0xff in loc_cfg.cpp
if that value remains unchanged, it means gps.conf did not
provide a value and we default to the initial value to use
Android's logging levels*/
/* Tag based logging control MACROS */
/* The logic is like this:
* 1, LOCAL_LOG_LEVEL is defined as a static variable in log_util.h,
* then all source files which includes log_util.h will have its own LOCAL_LOG_LEVEL variable;
* 2, For each source file,
* 2.1, First time when LOC_LOG* is invoked(its LOCAL_LOG_LEVEL == -1),
* Set the tag based log level according to the <tag, level> map;
* If this tag isn't found in map, set local debug level as global loc_logger.DEBUG_LEVEL;
* 2.2, If not the first time, use its LOCAL_LOG_LEVEL as the debug level of this tag.
*/
static int LOCAL_LOG_LEVEL = -1;
#define IF_LOC_LOG(x) \
if (((LOCAL_LOG_LEVEL == -1 && (LOCAL_LOG_LEVEL = get_tag_log_level(LOG_TAG)) >= x) ||\
LOCAL_LOG_LEVEL >= x) && LOCAL_LOG_LEVEL <= 5)
#define IF_LOC_LOGE IF_LOC_LOG(1)
#define IF_LOC_LOGW IF_LOC_LOG(2)
#define IF_LOC_LOGI IF_LOC_LOG(3)
#define IF_LOC_LOGD IF_LOC_LOG(4)
#define IF_LOC_LOGV IF_LOC_LOG(5)
#define LOC_LOGE(...) IF_LOC_LOGE { ALOGE(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 0, __VA_ARGS__);}
#define LOC_LOGW(...) IF_LOC_LOGW { ALOGW(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 1, __VA_ARGS__);}
#define LOC_LOGI(...) IF_LOC_LOGI { ALOGI(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 2, __VA_ARGS__);}
#define LOC_LOGD(...) IF_LOC_LOGD { ALOGD(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 3, __VA_ARGS__);}
#define LOC_LOGV(...) IF_LOC_LOGV { ALOGV(__VA_ARGS__); INSERT_BUFFER(LOG_NDEBUG, 4, __VA_ARGS__);}
#else /* DEBUG_DMN_LOC_API */
#define LOC_LOGE(...) ALOGE(__VA_ARGS__)
#define LOC_LOGW(...) ALOGW(__VA_ARGS__)
#define LOC_LOGI(...) ALOGI(__VA_ARGS__)
#define LOC_LOGD(...) ALOGD(__VA_ARGS__)
#define LOC_LOGV(...) ALOGV(__VA_ARGS__)
#endif /* DEBUG_DMN_LOC_API */
/*=============================================================================
*
* LOGGING IMPROVEMENT MACROS
*
*============================================================================*/
#define LOG_(LOC_LOG, ID, WHAT, SPEC, VAL) \
do { \
if (loc_logger.TIMESTAMP) { \
char ts[32]; \
LOC_LOG("[%s] %s %s line %d " #SPEC, \
get_timestamp(ts, sizeof(ts)), ID, WHAT, __LINE__, VAL); \
} else { \
LOC_LOG("%s %s line %d " #SPEC, \
ID, WHAT, __LINE__, VAL); \
} \
} while(0)
#define LOC_LOG_HEAD(fmt) "%s:%d] " fmt
#define LOC_LOGv(fmt,...) LOC_LOGV(LOC_LOG_HEAD(fmt), __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define LOC_LOGw(fmt,...) LOC_LOGW(LOC_LOG_HEAD(fmt), __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define LOC_LOGi(fmt,...) LOC_LOGI(LOC_LOG_HEAD(fmt), __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define LOC_LOGd(fmt,...) LOC_LOGD(LOC_LOG_HEAD(fmt), __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define LOC_LOGe(fmt,...) LOC_LOGE(LOC_LOG_HEAD(fmt), __FUNCTION__, __LINE__, ##__VA_ARGS__)
#define LOG_I(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGI, ID, WHAT, SPEC, VAL)
#define LOG_V(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGV, ID, WHAT, SPEC, VAL)
#define LOG_E(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGE, ID, WHAT, SPEC, VAL)
#define LOG_D(ID, WHAT, SPEC, VAL) LOG_(LOC_LOGD, ID, WHAT, SPEC, VAL)
#define ENTRY_LOG() LOG_V(ENTRY_TAG, __FUNCTION__, %s, "")
#define EXIT_LOG(SPEC, VAL) LOG_V(EXIT_TAG, __FUNCTION__, SPEC, VAL)
#define EXIT_LOG_WITH_ERROR(SPEC, VAL) \
if (VAL != 0) { \
LOG_E(EXIT_ERROR_TAG, __FUNCTION__, SPEC, VAL); \
} else { \
LOG_V(EXIT_TAG, __FUNCTION__, SPEC, VAL); \
}
// Used for logging callflow from Android Framework
#define ENTRY_LOG_CALLFLOW() LOG_I(FROM_AFW, __FUNCTION__, %s, "")
// Used for logging callflow to Modem
#define EXIT_LOG_CALLFLOW(SPEC, VAL) LOG_I(TO_MODEM, __FUNCTION__, SPEC, VAL)
// Used for logging callflow from Modem(TO_MODEM, __FUNCTION__, %s, "")
#define MODEM_LOG_CALLFLOW(SPEC, VAL) LOG_I(FROM_MODEM, __FUNCTION__, SPEC, VAL)
// Used for logging high frequency callflow from Modem(TO_MODEM, __FUNCTION__, %s, "")
#define MODEM_LOG_CALLFLOW_DEBUG(SPEC, VAL) LOG_D(FROM_MODEM, __FUNCTION__, SPEC, VAL)
// Used for logging callflow to Android Framework
#define CALLBACK_LOG_CALLFLOW(CB, SPEC, VAL) LOG_I(TO_AFW, CB, SPEC, VAL)
#ifdef __cplusplus
}
#endif
#endif // __LOG_UTIL_H__

380
gps/utils/msg_q.c Normal file
View file

@ -0,0 +1,380 @@
/* Copyright (c) 2011-2012, 2014, 2017 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.
*/
// Uncomment to log verbose logs
#define LOG_NDEBUG 1
#define LOG_TAG "LocSvc_utils_q"
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <loc_pla.h>
#include <log_util.h>
#include "linked_list.h"
#include "msg_q.h"
typedef struct msg_q {
void* msg_list; /* Linked list to store information */
pthread_cond_t list_cond; /* Condition variable for waiting on msg queue */
pthread_mutex_t list_mutex; /* Mutex for exclusive access to message queue */
int unblocked; /* Has this message queue been unblocked? */
} msg_q;
/*===========================================================================
FUNCTION convert_linked_list_err_type
DESCRIPTION
Converts from one set of enum values to another.
linked_list_val: Value to convert to msg_q_enum_type
DEPENDENCIES
N/A
RETURN VALUE
Corresponding linked_list_enum_type in msg_q_enum_type
SIDE EFFECTS
N/A
===========================================================================*/
static msq_q_err_type convert_linked_list_err_type(linked_list_err_type linked_list_val)
{
switch( linked_list_val )
{
case eLINKED_LIST_SUCCESS:
return eMSG_Q_SUCCESS;
case eLINKED_LIST_INVALID_PARAMETER:
return eMSG_Q_INVALID_PARAMETER;
case eLINKED_LIST_INVALID_HANDLE:
return eMSG_Q_INVALID_HANDLE;
case eLINKED_LIST_UNAVAILABLE_RESOURCE:
return eMSG_Q_UNAVAILABLE_RESOURCE;
case eLINKED_LIST_INSUFFICIENT_BUFFER:
return eMSG_Q_INSUFFICIENT_BUFFER;
case eLINKED_LIST_FAILURE_GENERAL:
default:
return eMSG_Q_FAILURE_GENERAL;
}
}
/* ----------------------- END INTERNAL FUNCTIONS ---------------------------------------- */
/*===========================================================================
FUNCTION: msg_q_init
===========================================================================*/
msq_q_err_type msg_q_init(void** msg_q_data)
{
if( msg_q_data == NULL )
{
LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
return eMSG_Q_INVALID_PARAMETER;
}
msg_q* tmp_msg_q;
tmp_msg_q = (msg_q*)calloc(1, sizeof(msg_q));
if( tmp_msg_q == NULL )
{
LOC_LOGE("%s: Unable to allocate space for message queue!\n", __FUNCTION__);
return eMSG_Q_FAILURE_GENERAL;
}
if( linked_list_init(&tmp_msg_q->msg_list) != 0 )
{
LOC_LOGE("%s: Unable to initialize storage list!\n", __FUNCTION__);
free(tmp_msg_q);
return eMSG_Q_FAILURE_GENERAL;
}
if( pthread_mutex_init(&tmp_msg_q->list_mutex, NULL) != 0 )
{
LOC_LOGE("%s: Unable to initialize list mutex!\n", __FUNCTION__);
linked_list_destroy(&tmp_msg_q->msg_list);
free(tmp_msg_q);
return eMSG_Q_FAILURE_GENERAL;
}
if( pthread_cond_init(&tmp_msg_q->list_cond, NULL) != 0 )
{
LOC_LOGE("%s: Unable to initialize msg q cond var!\n", __FUNCTION__);
linked_list_destroy(&tmp_msg_q->msg_list);
pthread_mutex_destroy(&tmp_msg_q->list_mutex);
free(tmp_msg_q);
return eMSG_Q_FAILURE_GENERAL;
}
tmp_msg_q->unblocked = 0;
*msg_q_data = tmp_msg_q;
return eMSG_Q_SUCCESS;
}
/*===========================================================================
FUNCTION: msg_q_init2
===========================================================================*/
const void* msg_q_init2()
{
void* q = NULL;
if (eMSG_Q_SUCCESS != msg_q_init(&q)) {
q = NULL;
}
return q;
}
/*===========================================================================
FUNCTION: msg_q_destroy
===========================================================================*/
msq_q_err_type msg_q_destroy(void** msg_q_data)
{
if( msg_q_data == NULL )
{
LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
return eMSG_Q_INVALID_HANDLE;
}
msg_q* p_msg_q = (msg_q*)*msg_q_data;
linked_list_destroy(&p_msg_q->msg_list);
pthread_mutex_destroy(&p_msg_q->list_mutex);
pthread_cond_destroy(&p_msg_q->list_cond);
p_msg_q->unblocked = 0;
free(*msg_q_data);
*msg_q_data = NULL;
return eMSG_Q_SUCCESS;
}
/*===========================================================================
FUNCTION: msg_q_snd
===========================================================================*/
msq_q_err_type msg_q_snd(void* msg_q_data, void* msg_obj, void (*dealloc)(void*))
{
msq_q_err_type rv;
if( msg_q_data == NULL )
{
LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
return eMSG_Q_INVALID_HANDLE;
}
if( msg_obj == NULL )
{
LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__);
return eMSG_Q_INVALID_PARAMETER;
}
msg_q* p_msg_q = (msg_q*)msg_q_data;
pthread_mutex_lock(&p_msg_q->list_mutex);
LOC_LOGV("%s: Sending message with handle = %p\n", __FUNCTION__, msg_obj);
if( p_msg_q->unblocked )
{
LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);
pthread_mutex_unlock(&p_msg_q->list_mutex);
return eMSG_Q_UNAVAILABLE_RESOURCE;
}
rv = convert_linked_list_err_type(linked_list_add(p_msg_q->msg_list, msg_obj, dealloc));
/* Show data is in the message queue. */
pthread_cond_signal(&p_msg_q->list_cond);
pthread_mutex_unlock(&p_msg_q->list_mutex);
LOC_LOGV("%s: Finished Sending message with handle = %p\n", __FUNCTION__, msg_obj);
return rv;
}
/*===========================================================================
FUNCTION: msg_q_rcv
===========================================================================*/
msq_q_err_type msg_q_rcv(void* msg_q_data, void** msg_obj)
{
msq_q_err_type rv;
if( msg_q_data == NULL )
{
LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
return eMSG_Q_INVALID_HANDLE;
}
if( msg_obj == NULL )
{
LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__);
return eMSG_Q_INVALID_PARAMETER;
}
msg_q* p_msg_q = (msg_q*)msg_q_data;
pthread_mutex_lock(&p_msg_q->list_mutex);
if( p_msg_q->unblocked )
{
LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);
pthread_mutex_unlock(&p_msg_q->list_mutex);
return eMSG_Q_UNAVAILABLE_RESOURCE;
}
/* Wait for data in the message queue */
while( linked_list_empty(p_msg_q->msg_list) && !p_msg_q->unblocked )
{
pthread_cond_wait(&p_msg_q->list_cond, &p_msg_q->list_mutex);
}
rv = convert_linked_list_err_type(linked_list_remove(p_msg_q->msg_list, msg_obj));
pthread_mutex_unlock(&p_msg_q->list_mutex);
LOC_LOGV("%s: Received message %p rv = %d\n", __FUNCTION__, *msg_obj, rv);
return rv;
}
/*===========================================================================
FUNCTION: msg_q_rmv
===========================================================================*/
msq_q_err_type msg_q_rmv(void* msg_q_data, void** msg_obj)
{
msq_q_err_type rv;
if (msg_q_data == NULL) {
LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
return eMSG_Q_INVALID_HANDLE;
}
if (msg_obj == NULL) {
LOC_LOGE("%s: Invalid msg_obj parameter!\n", __FUNCTION__);
return eMSG_Q_INVALID_PARAMETER;
}
msg_q* p_msg_q = (msg_q*)msg_q_data;
pthread_mutex_lock(&p_msg_q->list_mutex);
if (p_msg_q->unblocked) {
LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);
pthread_mutex_unlock(&p_msg_q->list_mutex);
return eMSG_Q_UNAVAILABLE_RESOURCE;
}
if (linked_list_empty(p_msg_q->msg_list)) {
LOC_LOGW("%s: list is empty !!\n", __FUNCTION__);
pthread_mutex_unlock(&p_msg_q->list_mutex);
return eLINKED_LIST_EMPTY;
}
rv = convert_linked_list_err_type(linked_list_remove(p_msg_q->msg_list, msg_obj));
pthread_mutex_unlock(&p_msg_q->list_mutex);
LOC_LOGV("%s: Removed message %p rv = %d\n", __FUNCTION__, *msg_obj, rv);
return rv;
}
/*===========================================================================
FUNCTION: msg_q_flush
===========================================================================*/
msq_q_err_type msg_q_flush(void* msg_q_data)
{
msq_q_err_type rv;
if ( msg_q_data == NULL )
{
LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
return eMSG_Q_INVALID_HANDLE;
}
msg_q* p_msg_q = (msg_q*)msg_q_data;
LOC_LOGD("%s: Flushing Message Queue\n", __FUNCTION__);
pthread_mutex_lock(&p_msg_q->list_mutex);
/* Remove all elements from the list */
rv = convert_linked_list_err_type(linked_list_flush(p_msg_q->msg_list));
pthread_mutex_unlock(&p_msg_q->list_mutex);
LOC_LOGD("%s: Message Queue flushed\n", __FUNCTION__);
return rv;
}
/*===========================================================================
FUNCTION: msg_q_unblock
===========================================================================*/
msq_q_err_type msg_q_unblock(void* msg_q_data)
{
if ( msg_q_data == NULL )
{
LOC_LOGE("%s: Invalid msg_q_data parameter!\n", __FUNCTION__);
return eMSG_Q_INVALID_HANDLE;
}
msg_q* p_msg_q = (msg_q*)msg_q_data;
pthread_mutex_lock(&p_msg_q->list_mutex);
if( p_msg_q->unblocked )
{
LOC_LOGE("%s: Message queue has been unblocked.\n", __FUNCTION__);
pthread_mutex_unlock(&p_msg_q->list_mutex);
return eMSG_Q_UNAVAILABLE_RESOURCE;
}
LOC_LOGD("%s: Unblocking Message Queue\n", __FUNCTION__);
/* Unblocking message queue */
p_msg_q->unblocked = 1;
/* Allow all the waiters to wake up */
pthread_cond_broadcast(&p_msg_q->list_cond);
pthread_mutex_unlock(&p_msg_q->list_mutex);
LOC_LOGD("%s: Message Queue unblocked\n", __FUNCTION__);
return eMSG_Q_SUCCESS;
}

230
gps/utils/msg_q.h Normal file
View file

@ -0,0 +1,230 @@
/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __MSG_Q_H__
#define __MSG_Q_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <stdlib.h>
/** Linked List Return Codes */
typedef enum
{
eMSG_Q_SUCCESS = 0,
/**< Request was successful. */
eMSG_Q_FAILURE_GENERAL = -1,
/**< Failed because of a general failure. */
eMSG_Q_INVALID_PARAMETER = -2,
/**< Failed because the request contained invalid parameters. */
eMSG_Q_INVALID_HANDLE = -3,
/**< Failed because an invalid handle was specified. */
eMSG_Q_UNAVAILABLE_RESOURCE = -4,
/**< Failed because an there were not enough resources. */
eMSG_Q_INSUFFICIENT_BUFFER = -5,
/**< Failed because an the supplied buffer was too small. */
}msq_q_err_type;
/*===========================================================================
FUNCTION msg_q_init
DESCRIPTION
Initializes internal structures for message queue.
msg_q_data: pointer to an opaque Q handle to be returned; NULL if fails
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
msq_q_err_type msg_q_init(void** msg_q_data);
/*===========================================================================
FUNCTION msg_q_init2
DESCRIPTION
Initializes internal structures for message queue.
DEPENDENCIES
N/A
RETURN VALUE
opaque handle to the Q created; NULL if create fails
SIDE EFFECTS
N/A
===========================================================================*/
const void* msg_q_init2();
/*===========================================================================
FUNCTION msg_q_destroy
DESCRIPTION
Releases internal structures for message queue.
msg_q_data: State of message queue to be released.
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
msq_q_err_type msg_q_destroy(void** msg_q_data);
/*===========================================================================
FUNCTION msg_q_snd
DESCRIPTION
Sends data to the message queue. The passed in data pointer
is not modified or freed. Passed in msg_obj is expected to live throughout
the use of the msg_q (i.e. data is not allocated internally)
msg_q_data: Message Queue to add the element to.
msgp: Pointer to data to add into message queue.
dealloc: Function used to deallocate memory for this element. Pass NULL
if you do not want data deallocated during a flush operation
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
msq_q_err_type msg_q_snd(void* msg_q_data, void* msg_obj, void (*dealloc)(void*));
/*===========================================================================
FUNCTION msg_q_rcv
DESCRIPTION
Retrieves data from the message queue. msg_obj is the oldest message received
and pointer is simply removed from message queue.
msg_q_data: Message Queue to copy data from into msgp.
msg_obj: Pointer to space to copy msg_q contents to.
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
msq_q_err_type msg_q_rcv(void* msg_q_data, void** msg_obj);
/*===========================================================================
FUNCTION msg_q_rmv
DESCRIPTION
Remove data from the message queue. msg_obj is the oldest message received
and pointer is simply removed from message queue.
msg_q_data: Message Queue to copy data from into msgp.
msg_obj: Pointer to space to copy msg_q contents to.
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
msq_q_err_type msg_q_rmv(void* msg_q_data, void** msg_obj);
/*===========================================================================
FUNCTION msg_q_flush
DESCRIPTION
Function removes all elements from the message queue.
msg_q_data: Message Queue to remove elements from.
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
msq_q_err_type msg_q_flush(void* msg_q_data);
/*===========================================================================
FUNCTION msg_q_unblock
DESCRIPTION
This function will stop use of the message queue. All waiters will wake up
and likely receive nothing from the queue resulting in a negative return
value. The message queue can no longer be used until it is destroyed
and initialized again after calling this function.
msg_q_data: Message queue to unblock.
DEPENDENCIES
N/A
RETURN VALUE
Look at error codes above.
SIDE EFFECTS
N/A
===========================================================================*/
msq_q_err_type msg_q_unblock(void* msg_q_data);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __MSG_Q_H__ */