mirror of
https://github.com/Evolution-X-Devices/device_xiaomi_sm6150-common
synced 2026-01-27 16:26:02 +00:00
davinci: gps: Import from LA.UM.8.9.r1-03800-sm6150.0
Change-Id: Idc1e896796742df928ef244bf003d24e87bfd3d7
This commit is contained in:
65
gps/utils/Android.mk
Normal file
65
gps/utils/Android.mk
Normal file
@@ -0,0 +1,65 @@
|
||||
ifneq ($(BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE),)
|
||||
ifneq ($(BUILD_TINY_ANDROID),true)
|
||||
#Compile this library only for builds with the latest modem image
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
|
||||
## Libs
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libdl \
|
||||
libutils \
|
||||
libcutils \
|
||||
liblog \
|
||||
libprocessgroup
|
||||
|
||||
LOCAL_SRC_FILES += \
|
||||
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
|
||||
|
||||
# Flag -std=c++11 is not accepted by compiler when LOCAL_CLANG is set to true
|
||||
LOCAL_CFLAGS += \
|
||||
-fno-short-enums \
|
||||
-D_ANDROID_
|
||||
|
||||
ifeq ($(TARGET_BUILD_VARIANT),user)
|
||||
LOCAL_CFLAGS += -DTARGET_BUILD_VARIANT_USER
|
||||
endif
|
||||
|
||||
LOCAL_LDFLAGS += -Wl,--export-dynamic
|
||||
|
||||
## Includes
|
||||
LOCAL_HEADER_LIBRARIES := \
|
||||
libutils_headers \
|
||||
libloc_pla_headers \
|
||||
liblocation_api_headers
|
||||
|
||||
LOCAL_MODULE := libgps.utils
|
||||
LOCAL_VENDOR_MODULE := true
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
|
||||
LOCAL_CFLAGS += $(GNSS_CFLAGS)
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := libgps.utils_headers
|
||||
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
|
||||
include $(BUILD_HEADER_LIBRARY)
|
||||
|
||||
endif # not BUILD_TINY_ANDROID
|
||||
endif # BOARD_VENDOR_QCOM_GPS_LOC_API_HARDWARE
|
||||
354
gps/utils/LocHeap.cpp
Normal file
354
gps/utils/LocHeap.cpp
Normal file
@@ -0,0 +1,354 @@
|
||||
/* Copyright (c) 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 <LocHeap.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef __LOC_UNIT_TEST__
|
||||
bool LocHeap::checkTree() {
|
||||
return ((NULL == mTree) || mTree->checkNodes());
|
||||
}
|
||||
uint32_t LocHeap::getTreeSize() {
|
||||
return (NULL == mTree) ? 0 : mTree->getSize();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __LOC_DEBUG__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
class LocHeapDebug : public LocHeap {
|
||||
public:
|
||||
bool checkTree() {
|
||||
return ((NULL == mTree) || mTree->checkNodes());
|
||||
}
|
||||
|
||||
uint32_t getTreeSize() {
|
||||
return (NULL == mTree) ? 0 : (mTree->getSize());
|
||||
}
|
||||
};
|
||||
|
||||
class LocHeapDebugData : public LocRankable {
|
||||
const int mID;
|
||||
public:
|
||||
LocHeapDebugData(int id) : mID(id) {}
|
||||
inline virtual int ranks(LocRankable& rankable) {
|
||||
LocHeapDebugData* testData = dynamic_cast<LocHeapDebugData*>(&rankable);
|
||||
return testData->mID - mID;
|
||||
}
|
||||
};
|
||||
|
||||
// For Linux command line testing:
|
||||
// compilation: g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -I. -I../../../../vendor/qcom/proprietary/gps-internal/unit-tests/fakes_for_host -I../../../../system/core/include LocHeap.cpp
|
||||
// test: valgrind --leak-check=full ./a.out 100
|
||||
int main(int argc, char** argv) {
|
||||
srand(time(NULL));
|
||||
int tries = atoi(argv[1]);
|
||||
int checks = tries >> 3;
|
||||
LocHeapDebug heap;
|
||||
int treeSize = 0;
|
||||
|
||||
for (int i = 0; i < tries; i++) {
|
||||
if (i % checks == 0 && !heap.checkTree()) {
|
||||
printf("tree check failed before %dth op\n", i);
|
||||
}
|
||||
int r = rand();
|
||||
|
||||
if (r & 1) {
|
||||
LocHeapDebugData* data = new LocHeapDebugData(r >> 1);
|
||||
heap.push(dynamic_cast<LocRankable&>(*data));
|
||||
treeSize++;
|
||||
} else {
|
||||
LocRankable* rankable = heap.pop();
|
||||
if (rankable) {
|
||||
delete rankable;
|
||||
}
|
||||
treeSize ? treeSize-- : 0;
|
||||
}
|
||||
|
||||
printf("%s: %d == %d\n", (r&1)?"push":"pop", treeSize, heap.getTreeSize());
|
||||
if (treeSize != heap.getTreeSize()) {
|
||||
printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||
tries = i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!heap.checkTree()) {
|
||||
printf("!!!!!!!!!!tree check failed at the end after %d ops!!!!!!!\n", tries);
|
||||
} else {
|
||||
printf("success!\n");
|
||||
}
|
||||
|
||||
for (LocRankable* data = heap.pop(); NULL != data; data = heap.pop()) {
|
||||
delete data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
96
gps/utils/LocHeap.h
Normal file
96
gps/utils/LocHeap.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* Copyright (c) 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_HEAP__
|
||||
#define __LOC_HEAP__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
#endif //__LOC_HEAP__
|
||||
436
gps/utils/LocIpc.cpp
Normal file
436
gps/utils/LocIpc.cpp
Normal file
@@ -0,0 +1,436 @@
|
||||
/* Copyright (c) 2017-2018 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 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(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 shared_ptr<ILocIpcListener>& dataCb, int sid, int flags,
|
||||
struct sockaddr *srcAddr, socklen_t *addrlen) const {
|
||||
ssize_t nBytes = -1;
|
||||
std::string msg(mMaxTxSize, 0);
|
||||
|
||||
if ((nBytes = ::recvfrom(sid, (void*)msg.data(), msg.size(), flags, srcAddr, addrlen)) > 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);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(make_shared<Sock>((nullptr == name) ? -1 : (::socket(AF_UNIX, SOCK_DGRAM, 0)))),
|
||||
mAddr({.sun_family = AF_UNIX, {}}) {
|
||||
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(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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
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(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(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() {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef NOT_DEFINED
|
||||
class LocIpcQcsiSender : public LocIpcSender {
|
||||
protected:
|
||||
inline virtual bool isOperable() const override {
|
||||
return mService != nullptr && mService->isServiceRegistered();
|
||||
}
|
||||
inline virtual ssize_t send(const uint8_t data[], uint32_t length, int32_t msgId) const override {
|
||||
return mService->sendIndToClient(msgId, data, length);
|
||||
}
|
||||
inline LocIpcQcsiSender(shared_ptr<QcsiService>& service) : mService(service) {}
|
||||
public:
|
||||
inline virtual ~LocIpcQcsi() {}
|
||||
};
|
||||
|
||||
class LocIpcQcsiRecver : public LocIpcQcsiSender, public LocIpcRecver {
|
||||
protected:
|
||||
inline virtual ssize_t recv() const override { return mService->recv(); }
|
||||
public:
|
||||
inline LocIpcQcsiRecver(unique_ptr<QcsiService>& service) :
|
||||
LocIpcQcsiSender(service), LocIpcRecver(mService->getDataCallback(), *this) {
|
||||
}
|
||||
// only the dele
|
||||
inline ~LocIpcQcsiRecver() {}
|
||||
inline virtual const char* getName() const override { return mService->getName().data(); };
|
||||
inline virtual void abort() const override { if (isSendable()) mService->abort(); }
|
||||
shared_ptr<LocIpcQcsiSender> getSender() { return make_pare<LocIpcQcsiSender>(mService); }
|
||||
};
|
||||
#endif
|
||||
|
||||
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 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 void abort() {
|
||||
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());
|
||||
mRunnable = new LocIpcRunnable(*this, ipcRecver);
|
||||
return mThread.start(threadName.c_str(), mRunnable);
|
||||
} 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() {
|
||||
if (mRunnable) {
|
||||
mRunnable->abort();
|
||||
mRunnable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
typedef unique_ptr<LocIpcRecver> (*creator_t)(const shared_ptr<ILocIpcListener>&, int, int);
|
||||
static creator_t creator = (creator_t)dlGetSymFromLib(sLibQrtrHandle, sLibQrtrName,
|
||||
#ifdef USE_GLIB
|
||||
"_ZN8loc_util22createLocIpcQrtrRecverERKSt10shared_ptrINS_15ILocIpcListenerEEii");
|
||||
#else
|
||||
"_ZN8loc_util22createLocIpcQrtrRecverERKNSt3__110shared_ptrINS_15ILocIpcListenerEEEii");
|
||||
#endif
|
||||
return (nullptr == creator) ? nullptr : creator(listener, service, instance);
|
||||
}
|
||||
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",
|
||||
"_ZN13QmiLocService41createLocIpcQmiLocServiceSenderRecverPairERKNSt3__110shared_ptrIN8loc_util15ILocIpcListenerEEEi");
|
||||
return (nullptr == creator) ?
|
||||
make_pair<shared_ptr<LocIpcSender>, unique_ptr<LocIpcRecver>>(nullptr, nullptr) :
|
||||
creator(listener, instance);
|
||||
}
|
||||
|
||||
}
|
||||
183
gps/utils/LocIpc.h
Normal file
183
gps/utils/LocIpc.h
Normal file
@@ -0,0 +1,183 @@
|
||||
/* Copyright (c) 2017-2018 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 <LocThread.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace loc_util {
|
||||
|
||||
|
||||
class LocIpcRecver;
|
||||
class LocIpcSender;
|
||||
class LocIpcRunnable;
|
||||
|
||||
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 length)= 0;
|
||||
};
|
||||
|
||||
|
||||
class LocIpc {
|
||||
public:
|
||||
inline LocIpc() : mRunnable(nullptr) {}
|
||||
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);
|
||||
static unique_ptr<LocIpcRecver>
|
||||
getLocIpcQrtrRecver(const shared_ptr<ILocIpcListener>& listener,
|
||||
int service, int instance);
|
||||
|
||||
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;
|
||||
LocIpcRunnable *mRunnable;
|
||||
};
|
||||
|
||||
/* 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 ~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 void informRecverRestarted() {}
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
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(); }
|
||||
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 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 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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //__LOC_IPC__
|
||||
77
gps/utils/LocSharedLock.h
Normal file
77
gps/utils/LocSharedLock.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* Copyright (c) 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_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 */
|
||||
// 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); }
|
||||
};
|
||||
|
||||
#endif //__LOC_SHARED_LOCK__
|
||||
266
gps/utils/LocThread.cpp
Normal file
266
gps/utils/LocThread.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
/* Copyright (c) 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 <LocThread.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <loc_pla.h>
|
||||
|
||||
class LocThreadDelegate {
|
||||
LocRunnable* mRunnable;
|
||||
bool mJoinable;
|
||||
pthread_t mThandle;
|
||||
pthread_mutex_t mMutex;
|
||||
int mRefCount;
|
||||
~LocThreadDelegate();
|
||||
LocThreadDelegate(LocThread::tCreate creator, const char* threadName,
|
||||
LocRunnable* runnable, bool joinable);
|
||||
void destroy();
|
||||
public:
|
||||
static LocThreadDelegate* create(LocThread::tCreate creator,
|
||||
const char* threadName, LocRunnable* runnable, bool joinable);
|
||||
void stop();
|
||||
// bye() is for the parent thread to go away. if joinable,
|
||||
// parent must stop the spawned thread, join, and then
|
||||
// destroy(); if detached, the parent can go straight
|
||||
// ahead to destroy()
|
||||
inline void bye() { mJoinable ? stop() : destroy(); }
|
||||
inline bool isRunning() { return (NULL != mRunnable); }
|
||||
static void* threadMain(void* arg);
|
||||
};
|
||||
|
||||
// it is important to note that internal members must be
|
||||
// initialized to values as if pthread_create succeeds.
|
||||
// This is to avoid the race condition between the threads,
|
||||
// once the thread is created, some of these values will
|
||||
// be check in the spawned thread, and must set correctly
|
||||
// then and there.
|
||||
// However, upon pthread_create failure, the data members
|
||||
// must be set to indicate failure, e.g. mRunnable, and
|
||||
// threashold approprietly for destroy(), e.g. mRefCount.
|
||||
LocThreadDelegate::LocThreadDelegate(LocThread::tCreate creator,
|
||||
const char* threadName, LocRunnable* runnable, bool joinable) :
|
||||
mRunnable(runnable), mJoinable(joinable), mThandle((pthread_t)NULL),
|
||||
mMutex(PTHREAD_MUTEX_INITIALIZER), mRefCount(2) {
|
||||
|
||||
// set up thread name, if nothing is passed in
|
||||
if (!threadName) {
|
||||
threadName = "LocThread";
|
||||
}
|
||||
|
||||
// create the thread here, then if successful
|
||||
// and a name is given, we set the thread name
|
||||
if (creator) {
|
||||
mThandle = creator(threadName, threadMain, this);
|
||||
} else if (pthread_create(&mThandle, NULL, threadMain, this)) {
|
||||
// pthread_create() failed
|
||||
mThandle = (pthread_t)NULL;
|
||||
}
|
||||
|
||||
if (mThandle) {
|
||||
// set thread name
|
||||
char lname[16];
|
||||
int len = (sizeof(lname) > (strlen(threadName) + 1)) ?
|
||||
(strlen(threadName)):(sizeof(lname) - 1);
|
||||
memcpy(lname, threadName, len);
|
||||
lname[len] = 0;
|
||||
// set the thread name here
|
||||
pthread_setname_np(mThandle, lname);
|
||||
|
||||
// detach, if not joinable
|
||||
if (!joinable) {
|
||||
pthread_detach(mThandle);
|
||||
}
|
||||
} else {
|
||||
// must set these values upon failure
|
||||
mRunnable = NULL;
|
||||
mJoinable = false;
|
||||
mRefCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
LocThreadDelegate::~LocThreadDelegate() {
|
||||
// at this point nothing should need done any more
|
||||
}
|
||||
|
||||
// factory method so that we could return NULL upon failure
|
||||
LocThreadDelegate* LocThreadDelegate::create(LocThread::tCreate creator,
|
||||
const char* threadName, LocRunnable* runnable, bool joinable) {
|
||||
LocThreadDelegate* thread = NULL;
|
||||
if (runnable) {
|
||||
thread = new LocThreadDelegate(creator, threadName, runnable, joinable);
|
||||
if (thread && !thread->isRunning()) {
|
||||
thread->destroy();
|
||||
thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return thread;
|
||||
}
|
||||
|
||||
// The order is importang
|
||||
// NULLing mRunnalbe stops the while loop in threadMain()
|
||||
// join() if mJoinble must come before destroy() call, as
|
||||
// the obj must remain alive at this time so that mThandle
|
||||
// remains valud.
|
||||
void LocThreadDelegate::stop() {
|
||||
// mRunnable and mJoinable are reset on different triggers.
|
||||
// mRunnable may get nulled on the spawned thread's way out;
|
||||
// or here.
|
||||
// mJouinable (if ever been true) gets falsed when client
|
||||
// thread triggers stop, with either a stop()
|
||||
// call or the client releases thread obj handle.
|
||||
if (mRunnable) {
|
||||
mRunnable = NULL;
|
||||
}
|
||||
if (mJoinable) {
|
||||
mJoinable = false;
|
||||
pthread_join(mThandle, NULL);
|
||||
}
|
||||
// call destroy() to possibly delete the obj
|
||||
destroy();
|
||||
}
|
||||
|
||||
// method for clients to call to release the obj
|
||||
// when it is a detached thread, the client thread
|
||||
// and the spawned thread can both try to destroy()
|
||||
// asynchronously. And we delete this obj when
|
||||
// mRefCount becomes 0.
|
||||
void LocThreadDelegate::destroy() {
|
||||
// else case shouldn't happen, unless there is a
|
||||
// leaking obj. But only our code here has such
|
||||
// obj, so if we test our code well, else case
|
||||
// will never happen
|
||||
if (mRefCount > 0) {
|
||||
// we need a flag on the stack
|
||||
bool callDelete = false;
|
||||
|
||||
// critical section between threads
|
||||
pthread_mutex_lock(&mMutex);
|
||||
// last destroy() call
|
||||
callDelete = (1 == mRefCount--);
|
||||
pthread_mutex_unlock(&mMutex);
|
||||
|
||||
// upon last destroy() call we delete this obj
|
||||
if (callDelete) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void* LocThreadDelegate::threadMain(void* arg) {
|
||||
LocThreadDelegate* locThread = (LocThreadDelegate*)(arg);
|
||||
|
||||
if (locThread) {
|
||||
LocRunnable* runnable = locThread->mRunnable;
|
||||
|
||||
if (runnable) {
|
||||
if (locThread->isRunning()) {
|
||||
runnable->prerun();
|
||||
}
|
||||
|
||||
while (locThread->isRunning() && runnable->run());
|
||||
|
||||
if (locThread->isRunning()) {
|
||||
runnable->postrun();
|
||||
}
|
||||
|
||||
// at this time, locThread->mRunnable may or may not be NULL
|
||||
// NULL it just to be safe and clean, as we want the field
|
||||
// in the released memory slot to be NULL.
|
||||
locThread->mRunnable = NULL;
|
||||
delete runnable;
|
||||
}
|
||||
locThread->destroy();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LocThread::~LocThread() {
|
||||
if (mThread) {
|
||||
mThread->bye();
|
||||
mThread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool LocThread::start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable) {
|
||||
bool success = false;
|
||||
if (!mThread) {
|
||||
mThread = LocThreadDelegate::create(creator, threadName, runnable, joinable);
|
||||
// true only if thread is created successfully
|
||||
success = (NULL != mThread);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void LocThread::stop() {
|
||||
if (mThread) {
|
||||
mThread->stop();
|
||||
mThread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __LOC_DEBUG__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
class LocRunnableTest1 : public LocRunnable {
|
||||
int mID;
|
||||
public:
|
||||
LocRunnableTest1(int id) : LocRunnable(), mID(id) {}
|
||||
virtual bool run() {
|
||||
printf("LocRunnableTest1: %d\n", mID++);
|
||||
sleep(1);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// on linux command line:
|
||||
// compile: g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -std=c++0x -I. -I../../../../vendor/qcom/proprietary/gps-internal/unit-tests/fakes_for_host -I../../../../system/core/include -lpthread LocThread.cpp
|
||||
// test detached thread: valgrind ./a.out 0
|
||||
// test joinable thread: valgrind ./a.out 1
|
||||
int main(int argc, char** argv) {
|
||||
LocRunnableTest1 test(10);
|
||||
|
||||
LocThread thread;
|
||||
thread.start("LocThreadTest", test, atoi(argv[1]));
|
||||
|
||||
sleep(10);
|
||||
|
||||
thread.stop();
|
||||
|
||||
sleep(5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
92
gps/utils/LocThread.h
Normal file
92
gps/utils/LocThread.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/* Copyright (c) 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_THREAD__
|
||||
#define __LOC_THREAD__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <pthread.h>
|
||||
|
||||
// abstract class to be implemented by client to provide a runnable class
|
||||
// which gets scheduled by LocThread
|
||||
class LocRunnable {
|
||||
public:
|
||||
inline LocRunnable() {}
|
||||
inline virtual ~LocRunnable() {}
|
||||
|
||||
// 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() {}
|
||||
};
|
||||
|
||||
// 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) {}
|
||||
virtual ~LocThread();
|
||||
|
||||
typedef pthread_t (*tCreate)(const char* name, void* (*start)(void*), void* arg);
|
||||
// client starts thread with a runnable, which implements
|
||||
// the logics to fun in the created thread context.
|
||||
// The thread could be either joinable or 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(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable = true);
|
||||
inline bool start(const char* threadName, LocRunnable* runnable, bool joinable = true) {
|
||||
return start(NULL, threadName, runnable, joinable);
|
||||
}
|
||||
|
||||
// NOTE: if this is a joinable thread, this stop may block
|
||||
// for a while until the thread is joined.
|
||||
void stop();
|
||||
|
||||
// thread status check
|
||||
inline bool isRunning() { return NULL != mThread; }
|
||||
};
|
||||
|
||||
#endif //__LOC_THREAD__
|
||||
753
gps/utils/LocTimer.cpp
Normal file
753
gps/utils/LocTimer.cpp
Normal file
@@ -0,0 +1,753 @@
|
||||
/* Copyright (c) 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 <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
|
||||
|
||||
/*
|
||||
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();
|
||||
};
|
||||
|
||||
// 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 : public LocRunnable {
|
||||
// the epoll fd
|
||||
const int mFd;
|
||||
// the thread that calls run() method
|
||||
LocThread* mThread;
|
||||
friend class LocThreadDelegate;
|
||||
// dtor
|
||||
~LocTimerPollTask();
|
||||
public:
|
||||
// ctor
|
||||
LocTimerPollTask();
|
||||
// this obj will be deleted once thread is deleted
|
||||
void destroy();
|
||||
// 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);
|
||||
// The polling thread context will call this method. This is where
|
||||
// epoll_wait() is blocking and waiting for events..
|
||||
virtual bool run();
|
||||
};
|
||||
|
||||
// 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", false);
|
||||
}
|
||||
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;
|
||||
LocHeapNode* mTree;
|
||||
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(new LocThread()) {
|
||||
// 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.
|
||||
if (!mThread->start("LocTimerPollTask", this)) {
|
||||
delete mThread;
|
||||
mThread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
LocTimerPollTask::~LocTimerPollTask() {
|
||||
// when fs is closed, epoll_wait() should fail run() should return false
|
||||
// and the spawned thread should exit.
|
||||
close(mFd);
|
||||
}
|
||||
|
||||
void LocTimerPollTask::destroy() {
|
||||
if (mThread) {
|
||||
LocThread* thread = mThread;
|
||||
mThread = NULL;
|
||||
delete thread;
|
||||
} else {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void LocTimerPollTask::addPoll(LocTimerContainer& timerContainer) {
|
||||
struct epoll_event ev;
|
||||
memset(&ev, 0, sizeof(ev));
|
||||
|
||||
ev.events = EPOLLIN | EPOLLWAKEUP;
|
||||
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 LocTimerPollTask::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();
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// This section above wraps for the C style APIs
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __LOC_DEBUG__
|
||||
|
||||
double getDeltaSeconds(struct timespec from, struct timespec to) {
|
||||
return (double)to.tv_sec + (double)to.tv_nsec / 1000000000
|
||||
- from.tv_sec - (double)from.tv_nsec / 1000000000;
|
||||
}
|
||||
|
||||
struct timespec getNow() {
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_BOOTTIME, &now);
|
||||
return now;
|
||||
}
|
||||
|
||||
class LocTimerTest : public LocTimer, public LocRankable {
|
||||
int mTimeOut;
|
||||
const struct timespec mTimeOfBirth;
|
||||
inline struct timespec getTimerWrapper(int timeout) {
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_BOOTTIME, &now);
|
||||
now.tv_sec += timeout;
|
||||
return now;
|
||||
}
|
||||
public:
|
||||
inline LocTimerTest(int timeout) : LocTimer(), LocRankable(),
|
||||
mTimeOut(timeout), mTimeOfBirth(getTimerWrapper(0)) {}
|
||||
inline virtual int ranks(LocRankable& rankable) {
|
||||
LocTimerTest* timer = dynamic_cast<LocTimerTest*>(&rankable);
|
||||
return timer->mTimeOut - mTimeOut;
|
||||
}
|
||||
inline virtual void timeOutCallback() {
|
||||
printf("timeOutCallback() - ");
|
||||
deviation();
|
||||
}
|
||||
double deviation() {
|
||||
struct timespec now = getTimerWrapper(0);
|
||||
double delta = getDeltaSeconds(mTimeOfBirth, now);
|
||||
printf("%lf: %lf\n", delta, delta * 100 / mTimeOut);
|
||||
return delta / mTimeOut;
|
||||
}
|
||||
};
|
||||
|
||||
// For Linux command line testing:
|
||||
// compilation:
|
||||
// g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -I. -I../../../../system/core/include -o LocHeap.o LocHeap.cpp
|
||||
// g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -std=c++0x -I. -I../../../../system/core/include -lpthread -o LocThread.o LocThread.cpp
|
||||
// g++ -D__LOC_HOST_DEBUG__ -D__LOC_DEBUG__ -g -I. -I../../../../system/core/include -o LocTimer.o LocTimer.cpp
|
||||
int main(int argc, char** argv) {
|
||||
struct timespec timeOfStart=getNow();
|
||||
srand(time(NULL));
|
||||
int tries = atoi(argv[1]);
|
||||
int checks = tries >> 3;
|
||||
LocTimerTest** timerArray = new LocTimerTest*[tries];
|
||||
memset(timerArray, NULL, tries);
|
||||
|
||||
for (int i = 0; i < tries; i++) {
|
||||
int r = rand() % tries;
|
||||
LocTimerTest* timer = new LocTimerTest(r);
|
||||
if (timerArray[r]) {
|
||||
if (!timer->stop()) {
|
||||
printf("%lf:\n", getDeltaSeconds(timeOfStart, getNow()));
|
||||
printf("ERRER: %dth timer, id %d, not running when it should be\n", i, r);
|
||||
exit(0);
|
||||
} else {
|
||||
printf("stop() - %d\n", r);
|
||||
delete timer;
|
||||
timerArray[r] = NULL;
|
||||
}
|
||||
} else {
|
||||
if (!timer->start(r, false)) {
|
||||
printf("%lf:\n", getDeltaSeconds(timeOfStart, getNow()));
|
||||
printf("ERRER: %dth timer, id %d, running when it should not be\n", i, r);
|
||||
exit(0);
|
||||
} else {
|
||||
printf("stop() - %d\n", r);
|
||||
timerArray[r] = timer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < tries; i++) {
|
||||
if (timerArray[i]) {
|
||||
if (!timerArray[i]->stop()) {
|
||||
printf("%lf:\n", getDeltaSeconds(timeOfStart, getNow()));
|
||||
printf("ERRER: %dth timer, not running when it should be\n", i);
|
||||
exit(0);
|
||||
} else {
|
||||
printf("stop() - %d\n", i);
|
||||
delete timerArray[i];
|
||||
timerArray[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] timerArray;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
74
gps/utils/LocTimer.h
Normal file
74
gps/utils/LocTimer.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* Copyright (c) 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_TIMER_CPP_H__
|
||||
#define __LOC_TIMER_CPP_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <loc_pla.h>
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
#endif //__LOC_DELAY_H__
|
||||
192
gps/utils/LocUnorderedSetMap.h
Normal file
192
gps/utils/LocUnorderedSetMap.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/* Copyright (c) 2015, 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 __LOC_UNORDERDED_SETMAP_H__
|
||||
#define __LOC_UNORDERDED_SETMAP_H__
|
||||
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
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(0);
|
||||
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) : mMap(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>(0);
|
||||
}
|
||||
|
||||
// This gets all the KEYs from the map
|
||||
inline unordered_set<KEY> getKeys() {
|
||||
unordered_set<KEY> keys(0);
|
||||
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(0);
|
||||
|
||||
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__
|
||||
72
gps/utils/Makefile.am
Normal file
72
gps/utils/Makefile.am
Normal file
@@ -0,0 +1,72 @@
|
||||
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 \
|
||||
loc_misc_utils.h \
|
||||
loc_nmea.h \
|
||||
gps_extended_c.h \
|
||||
gps_extended.h \
|
||||
loc_gps.h \
|
||||
log_util.h \
|
||||
LocSharedLock.h \
|
||||
LocUnorderedSetMap.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 \
|
||||
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)
|
||||
108
gps/utils/MsgTask.cpp
Normal file
108
gps/utils/MsgTask.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/* Copyright (c) 2011-2013, 2015, 2017The 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>
|
||||
|
||||
static void LocMsgDestroy(void* msg) {
|
||||
delete (LocMsg*)msg;
|
||||
}
|
||||
|
||||
MsgTask::MsgTask(LocThread::tCreate tCreator,
|
||||
const char* threadName, bool joinable) :
|
||||
mQ(msg_q_init2()), mThread(new LocThread()) {
|
||||
if (!mThread->start(tCreator, threadName, this, joinable)) {
|
||||
delete mThread;
|
||||
mThread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
MsgTask::MsgTask(const char* threadName, bool joinable) :
|
||||
mQ(msg_q_init2()), mThread(new LocThread()) {
|
||||
if (!mThread->start(threadName, this, joinable)) {
|
||||
delete mThread;
|
||||
mThread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
MsgTask::~MsgTask() {
|
||||
msg_q_flush((void*)mQ);
|
||||
msg_q_destroy((void**)&mQ);
|
||||
}
|
||||
|
||||
void MsgTask::destroy() {
|
||||
LocThread* thread = mThread;
|
||||
msg_q_unblock((void*)mQ);
|
||||
if (thread) {
|
||||
mThread = NULL;
|
||||
delete thread;
|
||||
} else {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
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::prerun() {
|
||||
#ifndef FEATURE_EXTERNAL_AP
|
||||
// make sure we do not run in background scheduling group
|
||||
set_sched_policy(gettid(), SP_FOREGROUND);
|
||||
#endif /* FEATURE_EXTERNAL_AP */
|
||||
}
|
||||
|
||||
bool MsgTask::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;
|
||||
}
|
||||
67
gps/utils/MsgTask.h
Normal file
67
gps/utils/MsgTask.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* Copyright (c) 2011-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 __MSG_TASK__
|
||||
#define __MSG_TASK__
|
||||
|
||||
#include <LocThread.h>
|
||||
|
||||
struct LocMsg {
|
||||
inline LocMsg() {}
|
||||
inline virtual ~LocMsg() {}
|
||||
virtual void proc() const = 0;
|
||||
inline virtual void log() const {}
|
||||
};
|
||||
|
||||
class MsgTask : public LocRunnable {
|
||||
const void* mQ;
|
||||
LocThread* mThread;
|
||||
friend class LocThreadDelegate;
|
||||
protected:
|
||||
virtual ~MsgTask();
|
||||
public:
|
||||
MsgTask(LocThread::tCreate tCreator, const char* threadName = NULL, bool joinable = true);
|
||||
MsgTask(const char* threadName = NULL, bool joinable = true);
|
||||
// this obj will be deleted once thread is deleted
|
||||
void destroy();
|
||||
void sendMsg(const LocMsg* msg) const;
|
||||
// Overrides of LocRunnable methods
|
||||
// This method will be repeated called until it returns false; or
|
||||
// until thread is stopped.
|
||||
virtual bool run();
|
||||
|
||||
// The method to be run before thread loop (conditionally repeatedly)
|
||||
// calls run()
|
||||
virtual void prerun();
|
||||
|
||||
// The method to be run after thread loop (conditionally repeatedly)
|
||||
// calls run()
|
||||
inline virtual void postrun() {}
|
||||
};
|
||||
|
||||
#endif //__MSG_TASK__
|
||||
92
gps/utils/configure.ac
Normal file
92
gps/utils/configure.ac
Normal 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])
|
||||
# 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
10
gps/utils/gps-utils.pc.in
Normal 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
114
gps/utils/gps_extended.h
Normal 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 */
|
||||
|
||||
2268
gps/utils/gps_extended_c.h
Normal file
2268
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
325
gps/utils/linked_list.c
Normal 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
219
gps/utils/linked_list.h
Normal 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__ */
|
||||
1067
gps/utils/loc_cfg.cpp
Normal file
1067
gps/utils/loc_cfg.cpp
Normal file
File diff suppressed because it is too large
Load Diff
143
gps/utils/loc_cfg.h
Normal file
143
gps/utils/loc_cfg.h
Normal file
@@ -0,0 +1,143 @@
|
||||
/* Copyright (c) 2011-2015, 2018 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), \
|
||||
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), sizeof(config_table) / sizeof(config_table[0]))
|
||||
|
||||
/*=============================================================================
|
||||
*
|
||||
* 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(const char* conf_file_name,
|
||||
const loc_param_s_type* config_table,
|
||||
uint32_t table_length);
|
||||
int loc_read_conf_r(FILE *conf_fp, const loc_param_s_type* config_table,
|
||||
uint32_t table_length);
|
||||
int loc_update_conf(const char* conf_data, int32_t length,
|
||||
const loc_param_s_type* config_table, uint32_t table_length);
|
||||
|
||||
// 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[];
|
||||
|
||||
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 */
|
||||
2229
gps/utils/loc_gps.h
Normal file
2229
gps/utils/loc_gps.h
Normal file
File diff suppressed because it is too large
Load Diff
238
gps/utils/loc_log.cpp
Normal file
238
gps/utils/loc_log.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
/* Copyright (c) 2011-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.
|
||||
*
|
||||
*/
|
||||
|
||||
#define LOG_NDEBUG 0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include "log_util.h"
|
||||
#include "loc_log.h"
|
||||
#include "msg_q.h"
|
||||
#include <loc_pla.h>
|
||||
|
||||
#define BUFFER_SIZE 120
|
||||
|
||||
// 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";
|
||||
|
||||
/* Logging Mechanism */
|
||||
loc_logger_s_type loc_logger;
|
||||
|
||||
/* Get names from value */
|
||||
const char* loc_get_name_from_mask(const loc_name_val_s_type table[], size_t table_size, long mask)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < table_size; i++)
|
||||
{
|
||||
if (table[i].val & (long) mask)
|
||||
{
|
||||
return table[i].name;
|
||||
}
|
||||
}
|
||||
return UNKNOWN_STR;
|
||||
}
|
||||
|
||||
/* Get names from value */
|
||||
const char* loc_get_name_from_val(const loc_name_val_s_type table[], size_t table_size, long value)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < table_size; i++)
|
||||
{
|
||||
if (table[i].val == (long) value)
|
||||
{
|
||||
return table[i].name;
|
||||
}
|
||||
}
|
||||
return UNKNOWN_STR;
|
||||
}
|
||||
|
||||
static const loc_name_val_s_type 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 )
|
||||
};
|
||||
static const size_t loc_msg_q_status_num = LOC_TABLE_SIZE(loc_msg_q_status);
|
||||
|
||||
/* Find msg_q status name */
|
||||
const char* loc_get_msg_q_status(int status)
|
||||
{
|
||||
return loc_get_name_from_val(loc_msg_q_status, loc_msg_q_status_num, (long) status);
|
||||
}
|
||||
|
||||
const char* log_succ_fail_string(int is_succ)
|
||||
{
|
||||
return is_succ? "successful" : "failed";
|
||||
}
|
||||
|
||||
//Target names
|
||||
static const loc_name_val_s_type 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)
|
||||
};
|
||||
|
||||
static const size_t target_name_num = LOC_TABLE_SIZE(target_name);
|
||||
|
||||
/*===========================================================================
|
||||
|
||||
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)
|
||||
{
|
||||
int index = 0;
|
||||
static char ret[BUFFER_SIZE];
|
||||
|
||||
index = getTargetGnssType(target);
|
||||
if( index < 0 || (unsigned)index >= target_name_num )
|
||||
index = target_name_num - 1;
|
||||
|
||||
if( (target & HAS_SSC) == HAS_SSC ) {
|
||||
snprintf(ret, sizeof(ret), " %s with SSC",
|
||||
loc_get_name_from_val(target_name, target_name_num, (long)index) );
|
||||
}
|
||||
else {
|
||||
snprintf(ret, sizeof(ret), " %s without SSC",
|
||||
loc_get_name_from_val(target_name, target_name_num, (long)index) );
|
||||
}
|
||||
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 loc_logger_init
|
||||
|
||||
DESCRIPTION
|
||||
Initializes the state of DEBUG_LEVEL and TIMESTAMP
|
||||
|
||||
DEPENDENCIES
|
||||
N/A
|
||||
|
||||
RETURN VALUE
|
||||
None
|
||||
|
||||
SIDE EFFECTS
|
||||
N/A
|
||||
===========================================================================*/
|
||||
void loc_logger_init(unsigned long debug, unsigned long timestamp)
|
||||
{
|
||||
loc_logger.DEBUG_LEVEL = debug;
|
||||
#ifdef TARGET_BUILD_VARIANT_USER
|
||||
// force user builds to 2 or less
|
||||
if (loc_logger.DEBUG_LEVEL > 2) {
|
||||
loc_logger.DEBUG_LEVEL = 2;
|
||||
}
|
||||
#endif
|
||||
loc_logger.TIMESTAMP = timestamp;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================
|
||||
FUNCTION get_timestamp
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
71
gps/utils/loc_log.h
Normal file
71
gps/utils/loc_log.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* Copyright (c) 2011-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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LOC_LOG_H
|
||||
#define LOC_LOG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include "loc_target.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
long val;
|
||||
} loc_name_val_s_type;
|
||||
|
||||
#define NAME_VAL(x) {"" #x "", x }
|
||||
|
||||
#define UNKNOWN_STR "UNKNOWN"
|
||||
|
||||
#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]))
|
||||
|
||||
/* Get names from value */
|
||||
const char* loc_get_name_from_mask(const loc_name_val_s_type table[], size_t table_size, long mask);
|
||||
const char* loc_get_name_from_val(const loc_name_val_s_type table[], size_t table_size, long value);
|
||||
const char* loc_get_msg_q_status(int status);
|
||||
const char* loc_get_target_name(unsigned int target);
|
||||
|
||||
extern const char* log_succ_fail_string(int is_succ);
|
||||
|
||||
extern char *loc_get_time(char *time_string, size_t buf_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LOC_LOG_H */
|
||||
145
gps/utils/loc_misc_utils.cpp
Normal file
145
gps/utils/loc_misc_utils.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/* Copyright (c) 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.
|
||||
*
|
||||
*/
|
||||
#define LOG_NDEBUG 0
|
||||
#define LOG_TAG "LocSvc_misc_utils"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <dlfcn.h>
|
||||
#include <log_util.h>
|
||||
#include <loc_misc_utils.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
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';
|
||||
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;
|
||||
}
|
||||
127
gps/utils/loc_misc_utils.h
Normal file
127
gps/utils/loc_misc_utils.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/* Copyright (c) 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_MISC_UTILS_H_
|
||||
#define _LOC_MISC_UTILS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*===========================================================================
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_LOC_MISC_UTILS_H_
|
||||
2088
gps/utils/loc_nmea.cpp
Normal file
2088
gps/utils/loc_nmea.cpp
Normal file
File diff suppressed because it is too large
Load Diff
92
gps/utils/loc_nmea.h
Normal file
92
gps/utils/loc_nmea.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/* Copyright (c) 2012-2013, 2015-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 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,
|
||||
std::vector<std::string> &nmeaArraystr);
|
||||
|
||||
#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
|
||||
210
gps/utils/loc_target.cpp
Normal file
210
gps/utils/loc_target.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
/* 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);
|
||||
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__);
|
||||
}
|
||||
}
|
||||
|
||||
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 id[] = "/sys/devices/soc0/soc_id";
|
||||
static const char hw_platform_dep[] =
|
||||
"/sys/devices/system/soc/soc0/hw_platform";
|
||||
static const char id_dep[] = "/sys/devices/system/soc/soc0/id";
|
||||
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);
|
||||
}
|
||||
if (!access(id, F_OK)) {
|
||||
read_a_line(id, rd_id, LINE_LEN);
|
||||
} else {
|
||||
read_a_line(id_dep, rd_id, LINE_LEN);
|
||||
}
|
||||
|
||||
/*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;
|
||||
}
|
||||
78
gps/utils/loc_target.h
Normal file
78
gps/utils/loc_target.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* 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);
|
||||
|
||||
/* 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
74
gps/utils/loc_timer.h
Normal 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__
|
||||
203
gps/utils/log_util.h
Normal file
203
gps/utils/log_util.h
Normal file
@@ -0,0 +1,203 @@
|
||||
/* Copyright (c) 2011-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 __LOG_UTIL_H__
|
||||
#define __LOG_UTIL_H__
|
||||
|
||||
#if defined (USE_ANDROID_LOGGING) || defined (ANDROID)
|
||||
// Android and LE targets with logcat support
|
||||
#include <utils/Log.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>
|
||||
|
||||
#ifndef LOG_TAG
|
||||
#define LOG_TAG "GPS_UTILS"
|
||||
#endif /* LOG_TAG */
|
||||
|
||||
// LE targets with no logcat support
|
||||
#ifdef FEATURE_EXTERNAL_AP
|
||||
#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;
|
||||
} loc_logger_s_type;
|
||||
|
||||
/*=============================================================================
|
||||
*
|
||||
* EXTERNAL DATA
|
||||
*
|
||||
*============================================================================*/
|
||||
extern loc_logger_s_type loc_logger;
|
||||
|
||||
// Logging Improvements
|
||||
extern const char *loc_logger_boolStr[];
|
||||
|
||||
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[];
|
||||
|
||||
/*=============================================================================
|
||||
*
|
||||
* MODULE EXPORTED FUNCTIONS
|
||||
*
|
||||
*============================================================================*/
|
||||
extern void loc_logger_init(unsigned long debug, unsigned long timestamp);
|
||||
extern char* get_timestamp(char* str, unsigned long buf_size);
|
||||
|
||||
#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*/
|
||||
#define IF_LOC_LOGE if((loc_logger.DEBUG_LEVEL >= 1) && (loc_logger.DEBUG_LEVEL <= 5))
|
||||
#define IF_LOC_LOGW if((loc_logger.DEBUG_LEVEL >= 2) && (loc_logger.DEBUG_LEVEL <= 5))
|
||||
#define IF_LOC_LOGI if((loc_logger.DEBUG_LEVEL >= 3) && (loc_logger.DEBUG_LEVEL <= 5))
|
||||
#define IF_LOC_LOGD if((loc_logger.DEBUG_LEVEL >= 4) && (loc_logger.DEBUG_LEVEL <= 5))
|
||||
#define IF_LOC_LOGV if((loc_logger.DEBUG_LEVEL >= 5) && (loc_logger.DEBUG_LEVEL <= 5))
|
||||
|
||||
#define LOC_LOGE(...) IF_LOC_LOGE { ALOGE(__VA_ARGS__); }
|
||||
#define LOC_LOGW(...) IF_LOC_LOGW { ALOGW(__VA_ARGS__); }
|
||||
#define LOC_LOGI(...) IF_LOC_LOGI { ALOGI(__VA_ARGS__); }
|
||||
#define LOC_LOGD(...) IF_LOC_LOGD { ALOGD(__VA_ARGS__); }
|
||||
#define LOC_LOGV(...) IF_LOC_LOGV { ALOGV(__VA_ARGS__); }
|
||||
|
||||
#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 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 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__
|
||||
378
gps/utils/msg_q.c
Normal file
378
gps/utils/msg_q.c
Normal file
@@ -0,0 +1,378 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#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
230
gps/utils/msg_q.h
Normal 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__ */
|
||||
Reference in New Issue
Block a user