432 lines
14 KiB
C++
432 lines
14 KiB
C++
/* Copyright (c) 2011-2013, 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_AGPS_H__
|
|
#define __LOC_ENG_AGPS_H__
|
|
|
|
#include <stdbool.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <arpa/inet.h>
|
|
#include <hardware/gps.h>
|
|
#include <gps_extended.h>
|
|
#include <loc_core_log.h>
|
|
#include <linked_list.h>
|
|
#include <loc_timer.h>
|
|
#include <LocEngAdapter.h>
|
|
|
|
// forward declaration
|
|
class AgpsStateMachine;
|
|
class Subscriber;
|
|
|
|
// NIF resource events
|
|
typedef enum {
|
|
RSRC_SUBSCRIBE,
|
|
RSRC_UNSUBSCRIBE,
|
|
RSRC_GRANTED,
|
|
RSRC_RELEASED,
|
|
RSRC_DENIED,
|
|
RSRC_STATUS_MAX
|
|
} AgpsRsrcStatus;
|
|
|
|
typedef enum {
|
|
servicerTypeNoCbParam,
|
|
servicerTypeAgps,
|
|
servicerTypeExt
|
|
}servicerType;
|
|
|
|
//DS Callback struct
|
|
typedef struct {
|
|
LocEngAdapter *mAdapter;
|
|
AGpsStatusValue action;
|
|
}dsCbData;
|
|
|
|
// information bundle for subscribers
|
|
struct Notification {
|
|
// goes to every subscriber
|
|
static const int BROADCAST_ALL;
|
|
// goes to every ACTIVE subscriber
|
|
static const int BROADCAST_ACTIVE;
|
|
// goes to every INACTIVE subscriber
|
|
static const int BROADCAST_INACTIVE;
|
|
|
|
// go to a specific subscriber
|
|
const Subscriber* rcver;
|
|
// broadcast
|
|
const int groupID;
|
|
// the new resource status event
|
|
const AgpsRsrcStatus rsrcStatus;
|
|
// should the subscriber be deleted after the notification
|
|
const bool postNotifyDelete;
|
|
|
|
// convenient constructor
|
|
inline Notification(const int broadcast,
|
|
const AgpsRsrcStatus status,
|
|
const bool deleteAfterwards) :
|
|
rcver(NULL), groupID(broadcast), rsrcStatus(status),
|
|
postNotifyDelete(deleteAfterwards) {}
|
|
|
|
// convenient constructor
|
|
inline Notification(const Subscriber* subscriber,
|
|
const AgpsRsrcStatus status,
|
|
const bool deleteAfterwards) :
|
|
rcver(subscriber), groupID(-1), rsrcStatus(status),
|
|
postNotifyDelete(deleteAfterwards) {}
|
|
|
|
// convenient constructor
|
|
inline Notification(const int broadcast) :
|
|
rcver(NULL), groupID(broadcast), rsrcStatus(RSRC_STATUS_MAX),
|
|
postNotifyDelete(false) {}
|
|
|
|
// convenient constructor
|
|
inline Notification(const Subscriber* subscriber) :
|
|
rcver(subscriber), groupID(-1), rsrcStatus(RSRC_STATUS_MAX),
|
|
postNotifyDelete(false) {}
|
|
};
|
|
|
|
class AgpsState {
|
|
// allows AgpsStateMachine to access private data
|
|
// no class members are public. We don't want
|
|
// anyone but state machine to use state.
|
|
friend class AgpsStateMachine;
|
|
friend class DSStateMachine;
|
|
// state transitions are done here.
|
|
// Each state implements its own transitions (of course).
|
|
inline virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data) = 0;
|
|
|
|
protected:
|
|
// handle back to state machine
|
|
const AgpsStateMachine* mStateMachine;
|
|
// each state has pointers to all 3 states
|
|
// one of which is to itself.
|
|
AgpsState* mReleasedState;
|
|
AgpsState* mAcquiredState;
|
|
AgpsState* mPendingState;
|
|
AgpsState* mReleasingState;
|
|
|
|
inline AgpsState(const AgpsStateMachine *stateMachine) :
|
|
mStateMachine(stateMachine),
|
|
mReleasedState(NULL),
|
|
mAcquiredState(NULL),
|
|
mPendingState(NULL),
|
|
mReleasingState(NULL) {}
|
|
virtual ~AgpsState() {}
|
|
|
|
public:
|
|
// for logging purpose
|
|
inline virtual char* whoami() = 0;
|
|
};
|
|
|
|
class Servicer {
|
|
void (*callback)(void);
|
|
public:
|
|
static Servicer* getServicer(servicerType type, void *cb_func);
|
|
virtual int requestRsrc(void *cb_data);
|
|
Servicer() {}
|
|
Servicer(void *cb_func)
|
|
{ callback = (void(*)(void))(cb_func); }
|
|
virtual ~Servicer(){}
|
|
inline virtual char *whoami() {return (char*)"Servicer";}
|
|
};
|
|
|
|
class ExtServicer : public Servicer {
|
|
int (*callbackExt)(void *cb_data);
|
|
public:
|
|
int requestRsrc(void *cb_data);
|
|
ExtServicer() {}
|
|
ExtServicer(void *cb_func)
|
|
{ callbackExt = (int(*)(void *))(cb_func); }
|
|
virtual ~ExtServicer(){}
|
|
inline virtual char *whoami() {return (char*)"ExtServicer";}
|
|
};
|
|
|
|
class AGpsServicer : public Servicer {
|
|
void (*callbackAGps)(AGpsStatus* status);
|
|
public:
|
|
int requestRsrc(void *cb_data);
|
|
AGpsServicer() {}
|
|
AGpsServicer(void *cb_func)
|
|
{ callbackAGps = (void(*)(AGpsStatus *))(cb_func); }
|
|
virtual ~AGpsServicer(){}
|
|
inline virtual char *whoami() {return (char*)"AGpsServicer";}
|
|
};
|
|
|
|
class AgpsStateMachine {
|
|
protected:
|
|
// a linked list of subscribers.
|
|
void* mSubscribers;
|
|
//handle to whoever provides the service
|
|
Servicer *mServicer;
|
|
// allows AgpsState to access private data
|
|
// each state is really internal data to the
|
|
// state machine, so it should be able to
|
|
// access anything within the state machine.
|
|
friend class AgpsState;
|
|
// pointer to the current state.
|
|
AgpsState* mStatePtr;
|
|
private:
|
|
// NIF type: AGNSS or INTERNET.
|
|
const AGpsExtType mType;
|
|
// apn to the NIF. Each state machine tracks
|
|
// resource state of a particular NIF. For each
|
|
// NIF, there is also an active APN.
|
|
char* mAPN;
|
|
// for convenience, we don't do strlen each time.
|
|
unsigned int mAPNLen;
|
|
// bear
|
|
AGpsBearerType mBearer;
|
|
// ipv4 address for routing
|
|
bool mEnforceSingleSubscriber;
|
|
|
|
public:
|
|
AgpsStateMachine(servicerType servType, void *cb_func,
|
|
AGpsExtType type, bool enforceSingleSubscriber);
|
|
virtual ~AgpsStateMachine();
|
|
|
|
// self explanatory methods below
|
|
void setAPN(const char* apn, unsigned int len);
|
|
inline const char* getAPN() const { return (const char*)mAPN; }
|
|
inline void setBearer(AGpsBearerType bearer) { mBearer = bearer; }
|
|
inline AGpsBearerType getBearer() const { return mBearer; }
|
|
inline AGpsExtType getType() const { return (AGpsExtType)mType; }
|
|
|
|
// someone, a ATL client or BIT, is asking for NIF
|
|
void subscribeRsrc(Subscriber *subscriber);
|
|
|
|
// someone, a ATL client or BIT, is done with NIF
|
|
bool unsubscribeRsrc(Subscriber *subscriber);
|
|
|
|
// add a subscriber in the linked list, if not already there.
|
|
void addSubscriber(Subscriber* subscriber) const;
|
|
|
|
virtual void onRsrcEvent(AgpsRsrcStatus event);
|
|
|
|
// put the data together and send the FW
|
|
virtual int sendRsrcRequest(AGpsStatusValue action) const;
|
|
|
|
//if list is empty, linked_list_empty returns 1
|
|
//else if list is not empty, returns 0
|
|
//so hasSubscribers() returns 1 if list is not empty
|
|
//and returns 0 if list is empty
|
|
inline bool hasSubscribers() const
|
|
{ return !linked_list_empty(mSubscribers); }
|
|
|
|
bool hasActiveSubscribers() const;
|
|
|
|
inline void dropAllSubscribers() const
|
|
{ linked_list_flush(mSubscribers); }
|
|
|
|
// private. Only a state gets to call this.
|
|
void notifySubscribers(Notification& notification) const;
|
|
|
|
};
|
|
|
|
class DSStateMachine : public AgpsStateMachine {
|
|
static const unsigned char MAX_START_DATA_CALL_RETRIES;
|
|
static const unsigned int DATA_CALL_RETRY_DELAY_MSEC;
|
|
LocEngAdapter* mLocAdapter;
|
|
unsigned char mRetries;
|
|
public:
|
|
DSStateMachine(servicerType type,
|
|
void *cb_func,
|
|
LocEngAdapter* adapterHandle);
|
|
int sendRsrcRequest(AGpsStatusValue action) const;
|
|
void onRsrcEvent(AgpsRsrcStatus event);
|
|
void retryCallback();
|
|
void informStatus(AgpsRsrcStatus status, int ID) const;
|
|
inline void incRetries() {mRetries++;}
|
|
inline virtual char *whoami() {return (char*)"DSStateMachine";}
|
|
};
|
|
|
|
// each subscriber is a AGPS client. In the case of ATL, there could be
|
|
// multiple clients from modem. In the case of BIT, there is only one
|
|
// cilent from BIT daemon.
|
|
struct Subscriber {
|
|
const uint32_t ID;
|
|
const AgpsStateMachine* mStateMachine;
|
|
inline Subscriber(const int id,
|
|
const AgpsStateMachine* stateMachine) :
|
|
ID(id), mStateMachine(stateMachine) {}
|
|
inline virtual ~Subscriber() {}
|
|
|
|
virtual void setIPAddresses(uint32_t &v4, char* v6) = 0;
|
|
virtual void setIPAddresses(struct sockaddr_storage& addr) = 0;
|
|
inline virtual void setWifiInfo(char* ssid, char* password)
|
|
{ ssid[0] = 0; password[0] = 0; }
|
|
|
|
inline virtual bool equals(const Subscriber *s) const
|
|
{ return ID == s->ID; }
|
|
|
|
// notifies a subscriber a new NIF resource status, usually
|
|
// either GRANTE, DENIED, or RELEASED
|
|
virtual bool notifyRsrcStatus(Notification ¬ification) = 0;
|
|
|
|
virtual bool waitForCloseComplete() { return false; }
|
|
virtual void setInactive() {}
|
|
virtual bool isInactive() { return false; }
|
|
|
|
virtual Subscriber* clone() = 0;
|
|
// checks if this notification is for me, i.e.
|
|
// either has my id, or has a broadcast id.
|
|
bool forMe(Notification ¬ification);
|
|
};
|
|
|
|
// BITSubscriber, created with requests from BIT daemon
|
|
struct BITSubscriber : public Subscriber {
|
|
char mIPv6Addr[16];
|
|
|
|
inline BITSubscriber(const AgpsStateMachine* stateMachine,
|
|
unsigned int ipv4, char* ipv6) :
|
|
Subscriber(ipv4, stateMachine)
|
|
{
|
|
if (NULL == ipv6) {
|
|
mIPv6Addr[0] = 0;
|
|
} else {
|
|
memcpy(mIPv6Addr, ipv6, sizeof(mIPv6Addr));
|
|
}
|
|
}
|
|
|
|
virtual bool notifyRsrcStatus(Notification ¬ification);
|
|
|
|
inline virtual void setIPAddresses(uint32_t &v4, char* v6)
|
|
{ v4 = ID; memcpy(v6, mIPv6Addr, sizeof(mIPv6Addr)); }
|
|
|
|
inline virtual void setIPAddresses(struct sockaddr_storage& addr)
|
|
{ addr.ss_family = AF_INET6;/*todo: convert mIPv6Addr into addr */ }
|
|
|
|
virtual Subscriber* clone()
|
|
{
|
|
return new BITSubscriber(mStateMachine, ID, mIPv6Addr);
|
|
}
|
|
|
|
virtual bool equals(const Subscriber *s) const;
|
|
inline virtual ~BITSubscriber(){}
|
|
};
|
|
|
|
// ATLSubscriber, created with requests from ATL
|
|
struct ATLSubscriber : public Subscriber {
|
|
const LocEngAdapter* mLocAdapter;
|
|
const bool mBackwardCompatibleMode;
|
|
inline ATLSubscriber(const int id,
|
|
const AgpsStateMachine* stateMachine,
|
|
const LocEngAdapter* adapter,
|
|
const bool compatibleMode) :
|
|
Subscriber(id, stateMachine), mLocAdapter(adapter),
|
|
mBackwardCompatibleMode(compatibleMode){}
|
|
virtual bool notifyRsrcStatus(Notification ¬ification);
|
|
|
|
inline virtual void setIPAddresses(uint32_t &v4, char* v6)
|
|
{ v4 = INADDR_NONE; v6[0] = 0; }
|
|
|
|
inline virtual void setIPAddresses(struct sockaddr_storage& addr)
|
|
{ addr.ss_family = AF_INET6; }
|
|
|
|
inline virtual Subscriber* clone()
|
|
{
|
|
return new ATLSubscriber(ID, mStateMachine, mLocAdapter,
|
|
mBackwardCompatibleMode);
|
|
}
|
|
inline virtual ~ATLSubscriber(){}
|
|
};
|
|
|
|
// WIFISubscriber, created with requests from MSAPM or QuIPC
|
|
struct WIFISubscriber : public Subscriber {
|
|
char * mSSID;
|
|
char * mPassword;
|
|
loc_if_req_sender_id_e_type senderId;
|
|
bool mIsInactive;
|
|
inline WIFISubscriber(const AgpsStateMachine* stateMachine,
|
|
char * ssid, char * password, loc_if_req_sender_id_e_type sender_id) :
|
|
Subscriber(sender_id, stateMachine),
|
|
mSSID(NULL == ssid ? NULL : new char[SSID_BUF_SIZE]),
|
|
mPassword(NULL == password ? NULL : new char[SSID_BUF_SIZE]),
|
|
senderId(sender_id)
|
|
{
|
|
if (NULL != mSSID)
|
|
strlcpy(mSSID, ssid, SSID_BUF_SIZE);
|
|
if (NULL != mPassword)
|
|
strlcpy(mPassword, password, SSID_BUF_SIZE);
|
|
mIsInactive = false;
|
|
}
|
|
|
|
virtual bool notifyRsrcStatus(Notification ¬ification);
|
|
|
|
inline virtual void setIPAddresses(uint32_t &v4, char* v6) {}
|
|
|
|
inline virtual void setIPAddresses(struct sockaddr_storage& addr)
|
|
{ addr.ss_family = AF_INET6; }
|
|
|
|
inline virtual void setWifiInfo(char* ssid, char* password)
|
|
{
|
|
if (NULL != mSSID)
|
|
strlcpy(ssid, mSSID, SSID_BUF_SIZE);
|
|
else
|
|
ssid[0] = '\0';
|
|
if (NULL != mPassword)
|
|
strlcpy(password, mPassword, SSID_BUF_SIZE);
|
|
else
|
|
password[0] = '\0';
|
|
}
|
|
|
|
inline virtual bool waitForCloseComplete() { return true; }
|
|
|
|
inline virtual void setInactive() { mIsInactive = true; }
|
|
inline virtual bool isInactive() { return mIsInactive; }
|
|
|
|
virtual Subscriber* clone()
|
|
{
|
|
return new WIFISubscriber(mStateMachine, mSSID, mPassword, senderId);
|
|
}
|
|
inline virtual ~WIFISubscriber(){}
|
|
};
|
|
|
|
struct DSSubscriber : public Subscriber {
|
|
bool mIsInactive;
|
|
inline DSSubscriber(const AgpsStateMachine *stateMachine,
|
|
const int id) :
|
|
Subscriber(id, stateMachine)
|
|
{
|
|
mIsInactive = false;
|
|
}
|
|
inline virtual void setIPAddresses(uint32_t &v4, char* v6) {}
|
|
inline virtual void setIPAddresses(struct sockaddr_storage& addr)
|
|
{ addr.ss_family = AF_INET6; }
|
|
virtual Subscriber* clone()
|
|
{return new DSSubscriber(mStateMachine, ID);}
|
|
virtual bool notifyRsrcStatus(Notification ¬ification);
|
|
inline virtual bool waitForCloseComplete() { return true; }
|
|
virtual void setInactive();
|
|
inline virtual bool isInactive()
|
|
{ return mIsInactive; }
|
|
inline virtual ~DSSubscriber(){}
|
|
inline virtual char *whoami() {return (char*)"DSSubscriber";}
|
|
};
|
|
|
|
#endif //__LOC_ENG_AGPS_H__
|