1/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above
9 *       copyright notice, this list of conditions and the following
10 *       disclaimer in the documentation and/or other materials provided
11 *       with the distribution.
12 *     * Neither the name of The Linux Foundation, nor the names of its
13 *       contributors may be used to endorse or promote products derived
14 *       from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#ifndef __LOC_ENG_AGPS_H__
31#define __LOC_ENG_AGPS_H__
32
33#include <stdbool.h>
34#include <ctype.h>
35#include <string.h>
36#include <arpa/inet.h>
37#include <hardware/gps.h>
38#include <gps_extended.h>
39#include <loc_core_log.h>
40#include <linked_list.h>
41#include <loc_timer.h>
42#include <LocEngAdapter.h>
43
44// forward declaration
45class AgpsStateMachine;
46class Subscriber;
47
48// NIF resource events
49typedef enum {
50    RSRC_SUBSCRIBE,
51    RSRC_UNSUBSCRIBE,
52    RSRC_GRANTED,
53    RSRC_RELEASED,
54    RSRC_DENIED,
55    RSRC_STATUS_MAX
56} AgpsRsrcStatus;
57
58typedef enum {
59    servicerTypeNoCbParam,
60    servicerTypeAgps,
61    servicerTypeExt
62}servicerType;
63
64//DS Callback struct
65typedef struct {
66    LocEngAdapter *mAdapter;
67    AGpsStatusValue action;
68}dsCbData;
69
70// information bundle for subscribers
71struct Notification {
72    // goes to every subscriber
73    static const int BROADCAST_ALL;
74    // goes to every ACTIVE subscriber
75    static const int BROADCAST_ACTIVE;
76    // goes to every INACTIVE subscriber
77    static const int BROADCAST_INACTIVE;
78
79    // go to a specific subscriber
80    const Subscriber* rcver;
81    // broadcast
82    const int groupID;
83    // the new resource status event
84    const AgpsRsrcStatus rsrcStatus;
85    // should the subscriber be deleted after the notification
86    const bool postNotifyDelete;
87
88    // convenient constructor
89    inline Notification(const int broadcast,
90                        const AgpsRsrcStatus status,
91                        const bool deleteAfterwards) :
92        rcver(NULL), groupID(broadcast), rsrcStatus(status),
93        postNotifyDelete(deleteAfterwards) {}
94
95    // convenient constructor
96    inline Notification(const Subscriber* subscriber,
97                        const AgpsRsrcStatus status,
98                        const bool deleteAfterwards) :
99        rcver(subscriber), groupID(-1), rsrcStatus(status),
100        postNotifyDelete(deleteAfterwards) {}
101
102    // convenient constructor
103    inline Notification(const int broadcast) :
104        rcver(NULL), groupID(broadcast), rsrcStatus(RSRC_STATUS_MAX),
105        postNotifyDelete(false) {}
106
107    // convenient constructor
108    inline Notification(const Subscriber* subscriber) :
109        rcver(subscriber), groupID(-1), rsrcStatus(RSRC_STATUS_MAX),
110        postNotifyDelete(false) {}
111};
112
113class AgpsState {
114    // allows AgpsStateMachine to access private data
115    // no class members are public.  We don't want
116    // anyone but state machine to use state.
117    friend class AgpsStateMachine;
118    friend class DSStateMachine;
119    // state transitions are done here.
120    // Each state implements its own transitions (of course).
121    inline virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data) = 0;
122
123protected:
124    // handle back to state machine
125    const AgpsStateMachine* mStateMachine;
126    // each state has pointers to all 3 states
127    // one of which is to itself.
128    AgpsState* mReleasedState;
129    AgpsState* mAcquiredState;
130    AgpsState* mPendingState;
131    AgpsState* mReleasingState;
132
133    inline AgpsState(const AgpsStateMachine *stateMachine) :
134        mStateMachine(stateMachine),
135        mReleasedState(NULL),
136        mAcquiredState(NULL),
137        mPendingState(NULL),
138        mReleasingState(NULL) {}
139    virtual ~AgpsState() {}
140
141public:
142    // for logging purpose
143    inline virtual char* whoami() = 0;
144};
145
146class Servicer {
147    void (*callback)(void);
148public:
149    static Servicer* getServicer(servicerType type, void *cb_func);
150    virtual int requestRsrc(void *cb_data);
151    Servicer() {}
152    Servicer(void *cb_func)
153    { callback = (void(*)(void))(cb_func); }
154    virtual ~Servicer(){}
155    inline virtual char *whoami() {return (char*)"Servicer";}
156};
157
158class ExtServicer : public Servicer {
159    int (*callbackExt)(void *cb_data);
160public:
161    int requestRsrc(void *cb_data);
162    ExtServicer() {}
163    ExtServicer(void *cb_func)
164    { callbackExt = (int(*)(void *))(cb_func); }
165    virtual ~ExtServicer(){}
166    inline virtual char *whoami() {return (char*)"ExtServicer";}
167};
168
169class AGpsServicer : public Servicer {
170    void (*callbackAGps)(AGpsStatus* status);
171public:
172    int requestRsrc(void *cb_data);
173    AGpsServicer() {}
174    AGpsServicer(void *cb_func)
175    { callbackAGps = (void(*)(AGpsStatus *))(cb_func); }
176    virtual ~AGpsServicer(){}
177    inline virtual char *whoami() {return (char*)"AGpsServicer";}
178};
179
180class AgpsStateMachine {
181protected:
182    // a linked list of subscribers.
183    void* mSubscribers;
184    //handle to whoever provides the service
185    Servicer *mServicer;
186    // allows AgpsState to access private data
187    // each state is really internal data to the
188    // state machine, so it should be able to
189    // access anything within the state machine.
190    friend class AgpsState;
191    // pointer to the current state.
192    AgpsState* mStatePtr;
193private:
194    // NIF type: AGNSS or INTERNET.
195    const AGpsExtType mType;
196    // apn to the NIF.  Each state machine tracks
197    // resource state of a particular NIF.  For each
198    // NIF, there is also an active APN.
199    char* mAPN;
200    // for convenience, we don't do strlen each time.
201    unsigned int mAPNLen;
202    // bear
203    AGpsBearerType mBearer;
204    // ipv4 address for routing
205    bool mEnforceSingleSubscriber;
206
207public:
208    AgpsStateMachine(servicerType servType, void *cb_func,
209                     AGpsExtType type, bool enforceSingleSubscriber);
210    virtual ~AgpsStateMachine();
211
212    // self explanatory methods below
213    void setAPN(const char* apn, unsigned int len);
214    inline const char* getAPN() const { return (const char*)mAPN; }
215    inline void setBearer(AGpsBearerType bearer) { mBearer = bearer; }
216    inline AGpsBearerType getBearer() const { return mBearer; }
217    inline AGpsExtType getType() const { return (AGpsExtType)mType; }
218
219    // someone, a ATL client or BIT, is asking for NIF
220    void subscribeRsrc(Subscriber *subscriber);
221
222    // someone, a ATL client or BIT, is done with NIF
223    bool unsubscribeRsrc(Subscriber *subscriber);
224
225    // add a subscriber in the linked list, if not already there.
226    void addSubscriber(Subscriber* subscriber) const;
227
228    virtual void onRsrcEvent(AgpsRsrcStatus event);
229
230    // put the data together and send the FW
231    virtual int sendRsrcRequest(AGpsStatusValue action) const;
232
233    //if list is empty, linked_list_empty returns 1
234    //else if list is not empty, returns 0
235    //so hasSubscribers() returns 1 if list is not empty
236    //and returns 0 if list is empty
237    inline bool hasSubscribers() const
238    { return !linked_list_empty(mSubscribers); }
239
240    bool hasActiveSubscribers() const;
241
242    inline void dropAllSubscribers() const
243    { linked_list_flush(mSubscribers); }
244
245    // private. Only a state gets to call this.
246    void notifySubscribers(Notification& notification) const;
247
248};
249
250class DSStateMachine : public AgpsStateMachine {
251    static const unsigned char MAX_START_DATA_CALL_RETRIES;
252    static const unsigned int DATA_CALL_RETRY_DELAY_MSEC;
253    LocEngAdapter* mLocAdapter;
254    unsigned char mRetries;
255public:
256    DSStateMachine(servicerType type,
257                   void *cb_func,
258                   LocEngAdapter* adapterHandle);
259    int sendRsrcRequest(AGpsStatusValue action) const;
260    void onRsrcEvent(AgpsRsrcStatus event);
261    void retryCallback();
262    void informStatus(AgpsRsrcStatus status, int ID) const;
263    inline void incRetries() {mRetries++;}
264    inline virtual char *whoami() {return (char*)"DSStateMachine";}
265};
266
267// each subscriber is a AGPS client.  In the case of ATL, there could be
268// multiple clients from modem.  In the case of BIT, there is only one
269// cilent from BIT daemon.
270struct Subscriber {
271    const uint32_t ID;
272    const AgpsStateMachine* mStateMachine;
273    inline Subscriber(const int id,
274                      const AgpsStateMachine* stateMachine) :
275        ID(id), mStateMachine(stateMachine) {}
276    inline virtual ~Subscriber() {}
277
278    virtual void setIPAddresses(uint32_t &v4, char* v6) = 0;
279    virtual void setIPAddresses(struct sockaddr_storage& addr) = 0;
280    inline virtual void setWifiInfo(char* ssid, char* password)
281    { ssid[0] = 0; password[0] = 0; }
282
283    inline virtual bool equals(const Subscriber *s) const
284    { return ID == s->ID; }
285
286    // notifies a subscriber a new NIF resource status, usually
287    // either GRANTE, DENIED, or RELEASED
288    virtual bool notifyRsrcStatus(Notification &notification) = 0;
289
290    virtual bool waitForCloseComplete() { return false; }
291    virtual void setInactive() {}
292    virtual bool isInactive() { return false; }
293
294    virtual Subscriber* clone() = 0;
295    // checks if this notification is for me, i.e.
296    // either has my id, or has a broadcast id.
297    bool forMe(Notification &notification);
298};
299
300// BITSubscriber, created with requests from BIT daemon
301struct BITSubscriber : public Subscriber {
302    char mIPv6Addr[16];
303
304    inline BITSubscriber(const AgpsStateMachine* stateMachine,
305                         unsigned int ipv4, char* ipv6) :
306        Subscriber(ipv4, stateMachine)
307    {
308        if (NULL == ipv6) {
309            mIPv6Addr[0] = 0;
310        } else {
311            memcpy(mIPv6Addr, ipv6, sizeof(mIPv6Addr));
312        }
313    }
314
315    virtual bool notifyRsrcStatus(Notification &notification);
316
317    inline virtual void setIPAddresses(uint32_t &v4, char* v6)
318    { v4 = ID; memcpy(v6, mIPv6Addr, sizeof(mIPv6Addr)); }
319
320    inline virtual void setIPAddresses(struct sockaddr_storage& addr)
321    { addr.ss_family = AF_INET6;/*todo: convert mIPv6Addr into addr */ }
322
323    virtual Subscriber* clone()
324    {
325        return new BITSubscriber(mStateMachine, ID, mIPv6Addr);
326    }
327
328    virtual bool equals(const Subscriber *s) const;
329    inline virtual ~BITSubscriber(){}
330};
331
332// ATLSubscriber, created with requests from ATL
333struct ATLSubscriber : public Subscriber {
334    const LocEngAdapter* mLocAdapter;
335    const bool mBackwardCompatibleMode;
336    inline ATLSubscriber(const int id,
337                         const AgpsStateMachine* stateMachine,
338                         const LocEngAdapter* adapter,
339                         const bool compatibleMode) :
340        Subscriber(id, stateMachine), mLocAdapter(adapter),
341        mBackwardCompatibleMode(compatibleMode){}
342    virtual bool notifyRsrcStatus(Notification &notification);
343
344    inline virtual void setIPAddresses(uint32_t &v4, char* v6)
345    { v4 = INADDR_NONE; v6[0] = 0; }
346
347    inline virtual void setIPAddresses(struct sockaddr_storage& addr)
348    { addr.ss_family = AF_INET6; }
349
350    inline virtual Subscriber* clone()
351    {
352        return new ATLSubscriber(ID, mStateMachine, mLocAdapter,
353                                 mBackwardCompatibleMode);
354    }
355    inline virtual ~ATLSubscriber(){}
356};
357
358// WIFISubscriber, created with requests from MSAPM or QuIPC
359struct WIFISubscriber : public Subscriber {
360    char * mSSID;
361    char * mPassword;
362    loc_if_req_sender_id_e_type senderId;
363    bool mIsInactive;
364    inline WIFISubscriber(const AgpsStateMachine* stateMachine,
365                         char * ssid, char * password, loc_if_req_sender_id_e_type sender_id) :
366        Subscriber(sender_id, stateMachine),
367        mSSID(NULL == ssid ? NULL : new char[SSID_BUF_SIZE]),
368        mPassword(NULL == password ? NULL : new char[SSID_BUF_SIZE]),
369        senderId(sender_id)
370    {
371      if (NULL != mSSID)
372          strlcpy(mSSID, ssid, SSID_BUF_SIZE);
373      if (NULL != mPassword)
374          strlcpy(mPassword, password, SSID_BUF_SIZE);
375      mIsInactive = false;
376    }
377
378    virtual bool notifyRsrcStatus(Notification &notification);
379
380    inline virtual void setIPAddresses(uint32_t &v4, char* v6) {}
381
382    inline virtual void setIPAddresses(struct sockaddr_storage& addr)
383    { addr.ss_family = AF_INET6; }
384
385    inline virtual void setWifiInfo(char* ssid, char* password)
386    {
387      if (NULL != mSSID)
388          strlcpy(ssid, mSSID, SSID_BUF_SIZE);
389      else
390          ssid[0] = '\0';
391      if (NULL != mPassword)
392          strlcpy(password, mPassword, SSID_BUF_SIZE);
393      else
394          password[0] = '\0';
395    }
396
397    inline virtual bool waitForCloseComplete() { return true; }
398
399    inline virtual void setInactive() { mIsInactive = true; }
400    inline virtual bool isInactive() { return mIsInactive; }
401
402    virtual Subscriber* clone()
403    {
404        return new WIFISubscriber(mStateMachine, mSSID, mPassword, senderId);
405    }
406    inline virtual ~WIFISubscriber(){}
407};
408
409struct DSSubscriber : public Subscriber {
410    bool mIsInactive;
411    inline DSSubscriber(const AgpsStateMachine *stateMachine,
412                         const int id) :
413        Subscriber(id, stateMachine)
414    {
415        mIsInactive = false;
416    }
417    inline virtual void setIPAddresses(uint32_t &v4, char* v6) {}
418    inline virtual void setIPAddresses(struct sockaddr_storage& addr)
419    { addr.ss_family = AF_INET6; }
420    virtual Subscriber* clone()
421    {return new DSSubscriber(mStateMachine, ID);}
422    virtual bool notifyRsrcStatus(Notification &notification);
423    inline virtual bool waitForCloseComplete() { return true; }
424    virtual void setInactive();
425    inline virtual bool isInactive()
426    { return mIsInactive; }
427    inline virtual ~DSSubscriber(){}
428    inline virtual char *whoami() {return (char*)"DSSubscriber";}
429};
430
431#endif //__LOC_ENG_AGPS_H__
432