blob: 2d689ceed0867398f943310cd93d04d156096b5d [file] [log] [blame]
/* 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 &notification) = 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 &notification);
};
// 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 &notification);
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 &notification);
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 &notification);
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 &notification);
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__