mirror of
https://github.com/LineageOS/android_device_xiaomi_whyred.git
synced 2025-10-04 02:09:23 +02:00
whyred: Import gps from LA.UM.6.2.r2-03600-sdm660.0
This commit is contained in:
parent
d7699194e4
commit
00cbc6eba8
142 changed files with 30786 additions and 0 deletions
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
|
Loading…
Add table
Add a link
Reference in a new issue