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#define LOG_NDDEBUG 0
31#define LOG_TAG "LocSvc_eng"
32
33#include <loc_eng_agps.h>
34#include <loc_eng_log.h>
35#include <log_util.h>
36#include <platform_lib_includes.h>
37#include <loc_eng_dmn_conn_handler.h>
38#include <loc_eng_dmn_conn.h>
39#include <sys/time.h>
40
41//======================================================================
42// C callbacks
43//======================================================================
44
45// This is given to linked_list_add as the dealloc callback
46// data -- an instance of Subscriber
47static void deleteObj(void* data)
48{
49    delete (Subscriber*)data;
50}
51
52// This is given to linked_list_search() as the comparison callback
53// when the state manchine needs to process for particular subscriber
54// fromCaller -- caller provides this obj
55// fromList -- linked_list_search() function take this one from list
56static bool hasSubscriber(void* fromCaller, void* fromList)
57{
58    Notification* notification = (Notification*)fromCaller;
59    Subscriber* s1 = (Subscriber*)fromList;
60
61    return s1->forMe(*notification);
62}
63
64// This is gvien to linked_list_search() to notify subscriber objs
65// when the state machine needs to inform all subscribers of resource
66// status changes, e.g. when resource is GRANTED.
67// fromCaller -- caller provides this ptr to a Notification obj.
68// fromList -- linked_list_search() function take this one from list
69static bool notifySubscriber(void* fromCaller, void* fromList)
70{
71    Notification* notification = (Notification*)fromCaller;
72    Subscriber* s1 = (Subscriber*)fromList;
73
74    // we notify every subscriber indiscriminatively
75    // each subscriber decides if this notification is interesting.
76    return s1->notifyRsrcStatus(*notification) &&
77           // if we do not want to delete the subscriber from the
78           // the list, we must set this to false so this function
79           // returns false
80           notification->postNotifyDelete;
81}
82
83//======================================================================
84// Notification
85//======================================================================
86const int Notification::BROADCAST_ALL = 0x80000000;
87const int Notification::BROADCAST_ACTIVE = 0x80000001;
88const int Notification::BROADCAST_INACTIVE = 0x80000002;
89const unsigned char DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4;
90const unsigned int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500;
91//======================================================================
92// Subscriber:  BITSubscriber / ATLSubscriber / WIFISubscriber
93//======================================================================
94bool Subscriber::forMe(Notification &notification)
95{
96    if (NULL != notification.rcver) {
97        return equals(notification.rcver);
98    } else {
99        return Notification::BROADCAST_ALL == notification.groupID ||
100            (Notification::BROADCAST_ACTIVE == notification.groupID &&
101             !isInactive()) ||
102            (Notification::BROADCAST_INACTIVE == notification.groupID &&
103             isInactive());
104    }
105}
106bool BITSubscriber::equals(const Subscriber *s) const
107{
108    BITSubscriber* bitS = (BITSubscriber*)s;
109
110    return (ID == bitS->ID &&
111            (INADDR_NONE != (unsigned int)ID ||
112             0 == strncmp(mIPv6Addr, bitS->mIPv6Addr, sizeof(mIPv6Addr))));
113}
114
115bool BITSubscriber::notifyRsrcStatus(Notification &notification)
116{
117    bool notify = forMe(notification);
118
119    if (notify) {
120        switch(notification.rsrcStatus)
121        {
122        case RSRC_UNSUBSCRIBE:
123        case RSRC_RELEASED:
124            loc_eng_dmn_conn_loc_api_server_data_conn(
125                LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON,
126                GPSONE_LOC_API_IF_RELEASE_SUCCESS);
127            break;
128        case RSRC_DENIED:
129            loc_eng_dmn_conn_loc_api_server_data_conn(
130                LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON,
131                GPSONE_LOC_API_IF_FAILURE);
132            break;
133        case RSRC_GRANTED:
134            loc_eng_dmn_conn_loc_api_server_data_conn(
135                LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON,
136                GPSONE_LOC_API_IF_REQUEST_SUCCESS);
137            break;
138        default:
139            notify = false;
140        }
141    }
142
143    return notify;
144}
145
146bool ATLSubscriber::notifyRsrcStatus(Notification &notification)
147{
148    bool notify = forMe(notification);
149
150    if (notify) {
151        switch(notification.rsrcStatus)
152        {
153        case RSRC_UNSUBSCRIBE:
154        case RSRC_RELEASED:
155            ((LocEngAdapter*)mLocAdapter)->atlCloseStatus(ID, 1);
156            break;
157        case RSRC_DENIED:
158        {
159            AGpsExtType type = mBackwardCompatibleMode ?
160                              AGPS_TYPE_INVALID : mStateMachine->getType();
161            ((LocEngAdapter*)mLocAdapter)->atlOpenStatus(ID, 0,
162                                            (char*)mStateMachine->getAPN(),
163                                            mStateMachine->getBearer(),
164                                            type);
165        }
166            break;
167        case RSRC_GRANTED:
168        {
169            AGpsExtType type = mBackwardCompatibleMode ?
170                              AGPS_TYPE_INVALID : mStateMachine->getType();
171            ((LocEngAdapter*)mLocAdapter)->atlOpenStatus(ID, 1,
172                                            (char*)mStateMachine->getAPN(),
173                                            mStateMachine->getBearer(),
174                                            type);
175        }
176            break;
177        default:
178            notify = false;
179        }
180    }
181
182    return notify;
183}
184
185bool WIFISubscriber::notifyRsrcStatus(Notification &notification)
186{
187    bool notify = forMe(notification);
188
189    if (notify) {
190        switch(notification.rsrcStatus)
191        {
192        case RSRC_UNSUBSCRIBE:
193            break;
194        case RSRC_RELEASED:
195            loc_eng_dmn_conn_loc_api_server_data_conn(
196                senderId,
197                GPSONE_LOC_API_IF_RELEASE_SUCCESS);
198            break;
199        case RSRC_DENIED:
200            loc_eng_dmn_conn_loc_api_server_data_conn(
201                senderId,
202                GPSONE_LOC_API_IF_FAILURE);
203            break;
204        case RSRC_GRANTED:
205            loc_eng_dmn_conn_loc_api_server_data_conn(
206                senderId,
207                GPSONE_LOC_API_IF_REQUEST_SUCCESS);
208            break;
209        default:
210            notify = false;
211        }
212    }
213
214    return notify;
215}
216bool DSSubscriber::notifyRsrcStatus(Notification &notification)
217{
218    bool notify = forMe(notification);
219    LOC_LOGD("DSSubscriber::notifyRsrcStatus. notify:%d \n",(int)(notify));
220    if(notify) {
221        switch(notification.rsrcStatus) {
222        case RSRC_UNSUBSCRIBE:
223        case RSRC_RELEASED:
224        case RSRC_DENIED:
225        case RSRC_GRANTED:
226            ((DSStateMachine *)mStateMachine)->informStatus(notification.rsrcStatus, ID);
227            break;
228        default:
229            notify = false;
230        }
231    }
232    return notify;
233}
234void DSSubscriber :: setInactive()
235{
236    mIsInactive = true;
237    ((DSStateMachine *)mStateMachine)->informStatus(RSRC_UNSUBSCRIBE, ID);
238}
239//======================================================================
240// AgpsState:  AgpsReleasedState / AgpsPendingState / AgpsAcquiredState
241//======================================================================
242
243// AgpsReleasedState
244class AgpsReleasedState : public AgpsState
245{
246    friend class AgpsStateMachine;
247
248    inline AgpsReleasedState(AgpsStateMachine* stateMachine) :
249        AgpsState(stateMachine)
250    { mReleasedState = this; }
251
252    inline ~AgpsReleasedState() {}
253public:
254    virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
255    inline virtual char* whoami() {return (char*)"AgpsReleasedState";}
256};
257
258AgpsState* AgpsReleasedState::onRsrcEvent(AgpsRsrcStatus event, void* data)
259{
260    LOC_LOGD("AgpsReleasedState::onRsrcEvent; event:%d\n", (int)event);
261    if (mStateMachine->hasSubscribers()) {
262        LOC_LOGE("Error: %s subscriber list not empty!!!", whoami());
263        // I don't know how to recover from it.  I am adding this rather
264        // for debugging purpose.
265    }
266
267    AgpsState* nextState = this;
268    switch (event)
269    {
270    case RSRC_SUBSCRIBE:
271    {
272        // no notification until we get RSRC_GRANTED
273        // but we need to add subscriber to the list
274        mStateMachine->addSubscriber((Subscriber*)data);
275        // request from connecivity service for NIF
276        //The if condition is added so that if the data call setup fails
277        //for DS State Machine, we want to retry in released state.
278        //for AGps State Machine, sendRsrcRequest() will always return success
279        if(!mStateMachine->sendRsrcRequest(GPS_REQUEST_AGPS_DATA_CONN)) {
280            // move the state to PENDING
281            nextState = mPendingState;
282        }
283    }
284    break;
285
286    case RSRC_UNSUBSCRIBE:
287    {
288        // the list should really be empty, nothing to remove.
289        // but we might as well just tell the client it is
290        // unsubscribed.  False tolerance, right?
291        Subscriber* subscriber = (Subscriber*) data;
292        Notification notification(subscriber, event, false);
293        subscriber->notifyRsrcStatus(notification);
294    }
295        // break;
296    case RSRC_GRANTED:
297    case RSRC_RELEASED:
298    case RSRC_DENIED:
299    default:
300        LOC_LOGW("%s: unrecognized event %d", whoami(), event);
301        // no state change.
302        break;
303    }
304
305    LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d",
306             whoami(), nextState->whoami(), event);
307    return nextState;
308}
309
310// AgpsPendingState
311class AgpsPendingState : public AgpsState
312{
313    friend class AgpsStateMachine;
314
315    inline AgpsPendingState(AgpsStateMachine* stateMachine) :
316        AgpsState(stateMachine)
317    { mPendingState = this; }
318
319    inline ~AgpsPendingState() {}
320public:
321    virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
322    inline virtual char* whoami() {return (char*)"AgpsPendingState";}
323};
324
325AgpsState* AgpsPendingState::onRsrcEvent(AgpsRsrcStatus event, void* data)
326{
327    AgpsState* nextState = this;;
328    LOC_LOGD("AgpsPendingState::onRsrcEvent; event:%d\n", (int)event);
329    switch (event)
330    {
331    case RSRC_SUBSCRIBE:
332    {
333        // already requested for NIF resource,
334        // do nothing until we get RSRC_GRANTED indication
335        // but we need to add subscriber to the list
336        mStateMachine->addSubscriber((Subscriber*)data);
337        // no state change.
338    }
339        break;
340
341    case RSRC_UNSUBSCRIBE:
342    {
343        Subscriber* subscriber = (Subscriber*) data;
344        if (subscriber->waitForCloseComplete()) {
345            subscriber->setInactive();
346        } else {
347            // auto notify this subscriber of the unsubscribe
348            Notification notification(subscriber, event, true);
349            mStateMachine->notifySubscribers(notification);
350        }
351
352        // now check if there is any subscribers left
353        if (!mStateMachine->hasSubscribers()) {
354            // no more subscribers, move to RELEASED state
355            nextState = mReleasedState;
356
357            // tell connecivity service we can release NIF
358            mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
359        } else if (!mStateMachine->hasActiveSubscribers()) {
360            // only inactive subscribers, move to RELEASING state
361            nextState = mReleasingState;
362
363            // tell connecivity service we can release NIF
364            mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
365        }
366    }
367    break;
368
369    case RSRC_GRANTED:
370    {
371        nextState = mAcquiredState;
372        Notification notification(Notification::BROADCAST_ACTIVE, event, false);
373        // notify all subscribers NIF resource GRANTED
374        // by setting false, we keep subscribers on the linked list
375        mStateMachine->notifySubscribers(notification);
376    }
377        break;
378
379    case RSRC_RELEASED:
380        // no state change.
381        // we are expecting either GRANTED or DENIED.  Handling RELEASED
382        // may like break our state machine in race conditions.
383        break;
384
385    case RSRC_DENIED:
386    {
387        nextState = mReleasedState;
388        Notification notification(Notification::BROADCAST_ALL, event, true);
389        // notify all subscribers NIF resource RELEASED or DENIED
390        // by setting true, we remove subscribers from the linked list
391        mStateMachine->notifySubscribers(notification);
392    }
393        break;
394
395    default:
396        LOC_LOGE("%s: unrecognized event %d", whoami(), event);
397        // no state change.
398    }
399
400    LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d",
401             whoami(), nextState->whoami(), event);
402    return nextState;
403}
404
405
406class AgpsAcquiredState : public AgpsState
407{
408    friend class AgpsStateMachine;
409
410    inline AgpsAcquiredState(AgpsStateMachine* stateMachine) :
411        AgpsState(stateMachine)
412    { mAcquiredState = this; }
413
414    inline ~AgpsAcquiredState() {}
415public:
416    virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
417    inline virtual char* whoami() { return (char*)"AgpsAcquiredState"; }
418};
419
420
421AgpsState* AgpsAcquiredState::onRsrcEvent(AgpsRsrcStatus event, void* data)
422{
423    AgpsState* nextState = this;
424    LOC_LOGD("AgpsAcquiredState::onRsrcEvent; event:%d\n", (int)event);
425    switch (event)
426    {
427    case RSRC_SUBSCRIBE:
428    {
429        // we already have the NIF resource, simply notify subscriber
430        Subscriber* subscriber = (Subscriber*) data;
431        // we have rsrc in hand, so grant it right away
432        Notification notification(subscriber, RSRC_GRANTED, false);
433        subscriber->notifyRsrcStatus(notification);
434        // add subscriber to the list
435        mStateMachine->addSubscriber(subscriber);
436        // no state change.
437    }
438        break;
439
440    case RSRC_UNSUBSCRIBE:
441    {
442        Subscriber* subscriber = (Subscriber*) data;
443        if (subscriber->waitForCloseComplete()) {
444            subscriber->setInactive();
445        } else {
446            // auto notify this subscriber of the unsubscribe
447            Notification notification(subscriber, event, true);
448            mStateMachine->notifySubscribers(notification);
449        }
450
451        // now check if there is any subscribers left
452        if (!mStateMachine->hasSubscribers()) {
453            // no more subscribers, move to RELEASED state
454            nextState = mReleasedState;
455
456            // tell connecivity service we can release NIF
457            mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
458        } else if (!mStateMachine->hasActiveSubscribers()) {
459            // only inactive subscribers, move to RELEASING state
460            nextState = mReleasingState;
461
462            // tell connecivity service we can release NIF
463            mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
464        }
465    }
466        break;
467
468    case RSRC_GRANTED:
469        LOC_LOGW("%s: %d, RSRC_GRANTED already received", whoami(), event);
470        // no state change.
471        break;
472
473    case RSRC_RELEASED:
474    {
475        LOC_LOGW("%s: %d, a force rsrc release", whoami(), event);
476        nextState = mReleasedState;
477        Notification notification(Notification::BROADCAST_ALL, event, true);
478        // by setting true, we remove subscribers from the linked list
479        mStateMachine->notifySubscribers(notification);
480    }
481        break;
482
483    case RSRC_DENIED:
484        // no state change.
485        // we are expecting RELEASED.  Handling DENIED
486        // may like break our state machine in race conditions.
487        break;
488
489    default:
490        LOC_LOGE("%s: unrecognized event %d", whoami(), event);
491        // no state change.
492    }
493
494    LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d",
495             whoami(), nextState->whoami(), event);
496    return nextState;
497}
498
499// AgpsPendingState
500class AgpsReleasingState : public AgpsState
501{
502    friend class AgpsStateMachine;
503
504    inline AgpsReleasingState(AgpsStateMachine* stateMachine) :
505        AgpsState(stateMachine)
506    { mReleasingState = this; }
507
508    inline ~AgpsReleasingState() {}
509public:
510    virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
511    inline virtual char* whoami() {return (char*)"AgpsReleasingState";}
512};
513
514AgpsState* AgpsReleasingState::onRsrcEvent(AgpsRsrcStatus event, void* data)
515{
516    AgpsState* nextState = this;;
517    LOC_LOGD("AgpsReleasingState::onRsrcEvent; event:%d\n", (int)event);
518
519   switch (event)
520    {
521    case RSRC_SUBSCRIBE:
522    {
523        // already requested for NIF resource,
524        // do nothing until we get RSRC_GRANTED indication
525        // but we need to add subscriber to the list
526        mStateMachine->addSubscriber((Subscriber*)data);
527        // no state change.
528    }
529        break;
530
531    case RSRC_UNSUBSCRIBE:
532    {
533        Subscriber* subscriber = (Subscriber*) data;
534        if (subscriber->waitForCloseComplete()) {
535            subscriber->setInactive();
536        } else {
537            // auto notify this subscriber of the unsubscribe
538            Notification notification(subscriber, event, true);
539            mStateMachine->notifySubscribers(notification);
540        }
541
542        // now check if there is any subscribers left
543        if (!mStateMachine->hasSubscribers()) {
544            // no more subscribers, move to RELEASED state
545            nextState = mReleasedState;
546        }
547    }
548        break;
549
550    case RSRC_DENIED:
551        // A race condition subscriber unsubscribes before AFW denies resource.
552    case RSRC_RELEASED:
553    {
554        nextState = mAcquiredState;
555        Notification notification(Notification::BROADCAST_INACTIVE, event, true);
556        // notify all subscribers that are active NIF resource RELEASE
557        // by setting false, we keep subscribers on the linked list
558        mStateMachine->notifySubscribers(notification);
559
560        if (mStateMachine->hasActiveSubscribers()) {
561            nextState = mPendingState;
562            // request from connecivity service for NIF
563            mStateMachine->sendRsrcRequest(GPS_REQUEST_AGPS_DATA_CONN);
564        } else {
565            nextState = mReleasedState;
566        }
567    }
568        break;
569
570    case RSRC_GRANTED:
571    default:
572        LOC_LOGE("%s: unrecognized event %d", whoami(), event);
573        // no state change.
574    }
575
576    LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d",
577             whoami(), nextState->whoami(), event);
578    return nextState;
579}
580//======================================================================
581//Servicer
582//======================================================================
583Servicer* Servicer :: getServicer(servicerType type, void *cb_func)
584{
585    LOC_LOGD(" Enter getServicer type:%d\n", (int)type);
586    switch(type) {
587    case servicerTypeNoCbParam:
588        return (new Servicer(cb_func));
589    case servicerTypeExt:
590        return (new ExtServicer(cb_func));
591    case servicerTypeAgps:
592        return (new AGpsServicer(cb_func));
593    default:
594        return NULL;
595    }
596}
597
598int Servicer :: requestRsrc(void *cb_data)
599{
600    callback();
601    return 0;
602}
603
604int ExtServicer :: requestRsrc(void *cb_data)
605{
606    int ret=-1;
607    LOC_LOGD("Enter ExtServicer :: requestRsrc\n");
608    ret = callbackExt(cb_data);
609    LOC_LOGD("Exit ExtServicer :: requestRsrc\n");
610    return(ret);
611}
612
613int AGpsServicer :: requestRsrc(void *cb_data)
614{
615    callbackAGps((AGpsStatus *)cb_data);
616    return 0;
617}
618
619//======================================================================
620// AgpsStateMachine
621//======================================================================
622
623AgpsStateMachine::AgpsStateMachine(servicerType servType,
624                                   void *cb_func,
625                                   AGpsExtType type,
626                                   bool enforceSingleSubscriber) :
627    mStatePtr(new AgpsReleasedState(this)),mType(type),
628    mAPN(NULL),
629    mAPNLen(0),
630    mBearer(AGPS_APN_BEARER_INVALID),
631    mEnforceSingleSubscriber(enforceSingleSubscriber),
632    mServicer(Servicer :: getServicer(servType, (void *)cb_func))
633{
634    linked_list_init(&mSubscribers);
635
636    // setting up mReleasedState
637    mStatePtr->mPendingState = new AgpsPendingState(this);
638    mStatePtr->mAcquiredState = new AgpsAcquiredState(this);
639    mStatePtr->mReleasingState = new AgpsReleasingState(this);
640
641    // setting up mAcquiredState
642    mStatePtr->mAcquiredState->mReleasedState = mStatePtr;
643    mStatePtr->mAcquiredState->mPendingState = mStatePtr->mPendingState;
644    mStatePtr->mAcquiredState->mReleasingState = mStatePtr->mReleasingState;
645
646    // setting up mPendingState
647    mStatePtr->mPendingState->mAcquiredState = mStatePtr->mAcquiredState;
648    mStatePtr->mPendingState->mReleasedState = mStatePtr;
649    mStatePtr->mPendingState->mReleasingState = mStatePtr->mReleasingState;
650
651    // setting up mReleasingState
652    mStatePtr->mReleasingState->mReleasedState = mStatePtr;
653    mStatePtr->mReleasingState->mPendingState = mStatePtr->mPendingState;
654    mStatePtr->mReleasingState->mAcquiredState = mStatePtr->mAcquiredState;
655}
656
657AgpsStateMachine::~AgpsStateMachine()
658{
659    dropAllSubscribers();
660
661    // free the 3 states.  We must read out all 3 pointers first.
662    // Otherwise we run the risk of getting pointers from already
663    // freed memory.
664    AgpsState* acquiredState = mStatePtr->mAcquiredState;
665    AgpsState* releasedState = mStatePtr->mReleasedState;
666    AgpsState* pendindState = mStatePtr->mPendingState;
667    AgpsState* releasingState = mStatePtr->mReleasingState;
668
669    delete acquiredState;
670    delete releasedState;
671    delete pendindState;
672    delete releasingState;
673    delete mServicer;
674    linked_list_destroy(&mSubscribers);
675
676    if (NULL != mAPN) {
677        delete[] mAPN;
678        mAPN = NULL;
679    }
680}
681
682void AgpsStateMachine::setAPN(const char* apn, unsigned int len)
683{
684    if (NULL != mAPN) {
685        delete mAPN;
686    }
687
688    if (NULL != apn) {
689        mAPN = new char[len+1];
690        memcpy(mAPN, apn, len);
691        mAPN[len] = NULL;
692
693        mAPNLen = len;
694    } else {
695        mAPN = NULL;
696        mAPNLen = 0;
697    }
698}
699
700void AgpsStateMachine::onRsrcEvent(AgpsRsrcStatus event)
701{
702    switch (event)
703    {
704    case RSRC_GRANTED:
705    case RSRC_RELEASED:
706    case RSRC_DENIED:
707        mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
708        break;
709    default:
710        LOC_LOGW("AgpsStateMachine: unrecognized event %d", event);
711        break;
712    }
713}
714
715void AgpsStateMachine::notifySubscribers(Notification& notification) const
716{
717    if (notification.postNotifyDelete) {
718        // just any non NULL value to get started
719        Subscriber* s = (Subscriber*)~0;
720        while (NULL != s) {
721            s = NULL;
722            // if the last param sets to true, _search will delete
723            // the node from the list for us.  But the problem is
724            // once that is done, _search returns, leaving the
725            // rest of the list unprocessed.  So we need a loop.
726            linked_list_search(mSubscribers, (void**)&s, notifySubscriber,
727                               (void*)&notification, true);
728            delete s;
729        }
730    } else {
731        // no loop needed if it the last param sets to false, which
732        // mean nothing gets deleted from the list.
733        linked_list_search(mSubscribers, NULL, notifySubscriber,
734                           (void*)&notification, false);
735    }
736}
737
738void AgpsStateMachine::addSubscriber(Subscriber* subscriber) const
739{
740    Subscriber* s = NULL;
741    Notification notification((const Subscriber*)subscriber);
742    linked_list_search(mSubscribers, (void**)&s,
743                       hasSubscriber, (void*)&notification, false);
744
745    if (NULL == s) {
746        linked_list_add(mSubscribers, subscriber->clone(), deleteObj);
747    }
748}
749
750int AgpsStateMachine::sendRsrcRequest(AGpsStatusValue action) const
751{
752    Subscriber* s = NULL;
753    Notification notification(Notification::BROADCAST_ACTIVE);
754    linked_list_search(mSubscribers, (void**)&s, hasSubscriber,
755                       (void*)&notification, false);
756
757    if ((NULL == s) == (GPS_RELEASE_AGPS_DATA_CONN == action)) {
758        AGpsExtStatus nifRequest;
759        nifRequest.size = sizeof(nifRequest);
760        nifRequest.type = mType;
761        nifRequest.status = action;
762
763        if (s == NULL) {
764            nifRequest.ipv4_addr = INADDR_NONE;
765            nifRequest.ipv6_addr[0] = 0;
766            nifRequest.ssid[0] = '\0';
767            nifRequest.password[0] = '\0';
768        } else {
769            s->setIPAddresses(nifRequest.ipv4_addr, (char*)nifRequest.ipv6_addr);
770            s->setWifiInfo(nifRequest.ssid, nifRequest.password);
771        }
772
773        CALLBACK_LOG_CALLFLOW("agps_cb", %s, loc_get_agps_status_name(action));
774        mServicer->requestRsrc((void *)&nifRequest);
775    }
776    return 0;
777}
778
779void AgpsStateMachine::subscribeRsrc(Subscriber *subscriber)
780{
781  if (mEnforceSingleSubscriber && hasSubscribers()) {
782      Notification notification(Notification::BROADCAST_ALL, RSRC_DENIED, true);
783      notifySubscriber(&notification, subscriber);
784  } else {
785      mStatePtr = mStatePtr->onRsrcEvent(RSRC_SUBSCRIBE, (void*)subscriber);
786  }
787}
788
789bool AgpsStateMachine::unsubscribeRsrc(Subscriber *subscriber)
790{
791    Subscriber* s = NULL;
792    Notification notification((const Subscriber*)subscriber);
793    linked_list_search(mSubscribers, (void**)&s,
794                       hasSubscriber, (void*)&notification, false);
795
796    if (NULL != s) {
797        mStatePtr = mStatePtr->onRsrcEvent(RSRC_UNSUBSCRIBE, (void*)s);
798        return true;
799    }
800    return false;
801}
802
803bool AgpsStateMachine::hasActiveSubscribers() const
804{
805    Subscriber* s = NULL;
806    Notification notification(Notification::BROADCAST_ACTIVE);
807    linked_list_search(mSubscribers, (void**)&s,
808                       hasSubscriber, (void*)&notification, false);
809    return NULL != s;
810}
811
812//======================================================================
813// DSStateMachine
814//======================================================================
815void delay_callback(void *callbackData, int result)
816{
817    if(callbackData) {
818        DSStateMachine *DSSMInstance = (DSStateMachine *)callbackData;
819        DSSMInstance->retryCallback();
820    }
821    else {
822        LOC_LOGE(" NULL argument received. Failing.\n");
823        goto err;
824    }
825err:
826    return;
827}
828
829DSStateMachine :: DSStateMachine(servicerType type, void *cb_func,
830                                 LocEngAdapter* adapterHandle):
831    AgpsStateMachine(type, cb_func, AGPS_TYPE_INVALID,false),
832    mLocAdapter(adapterHandle)
833{
834    LOC_LOGD("%s:%d]: New DSStateMachine\n", __func__, __LINE__);
835    mRetries = 0;
836}
837
838void DSStateMachine :: retryCallback(void)
839{
840    DSSubscriber *subscriber = NULL;
841    Notification notification(Notification::BROADCAST_ACTIVE);
842    linked_list_search(mSubscribers, (void**)&subscriber, hasSubscriber,
843                       (void*)&notification, false);
844    if(subscriber)
845        mLocAdapter->requestSuplES(subscriber->ID);
846    else
847        LOC_LOGE("DSStateMachine :: retryCallback: No subscriber found." \
848                 "Cannot retry data call\n");
849    return;
850}
851
852int DSStateMachine :: sendRsrcRequest(AGpsStatusValue action) const
853{
854    DSSubscriber* s = NULL;
855    dsCbData cbData;
856    int ret=-1;
857    int connHandle=-1;
858    LOC_LOGD("Enter DSStateMachine :: sendRsrcRequest\n");
859    Notification notification(Notification::BROADCAST_ACTIVE);
860    linked_list_search(mSubscribers, (void**)&s, hasSubscriber,
861                       (void*)&notification, false);
862    if(s) {
863        connHandle = s->ID;
864        LOC_LOGD("DSStateMachine :: sendRsrcRequest - subscriber found\n");
865    }
866    else
867        LOC_LOGD("DSStateMachine :: sendRsrcRequest - No subscriber found\n");
868
869    cbData.action = action;
870    cbData.mAdapter = mLocAdapter;
871    ret = mServicer->requestRsrc((void *)&cbData);
872    //Only the request to start data call returns a success/failure
873    //The request to stop data call will always succeed
874    //Hence, the below block will only be executed when the
875    //request to start the data call fails
876    switch(ret) {
877    case LOC_API_ADAPTER_ERR_ENGINE_BUSY:
878        LOC_LOGD("DSStateMachine :: sendRsrcRequest - Failure returned: %d\n",ret);
879        ((DSStateMachine *)this)->incRetries();
880        if(mRetries > MAX_START_DATA_CALL_RETRIES) {
881            LOC_LOGE(" Failed to start Data call. Fallback to normal ATL SUPL\n");
882            informStatus(RSRC_DENIED, connHandle);
883        }
884        else {
885            if(loc_timer_start(DATA_CALL_RETRY_DELAY_MSEC, delay_callback, (void *)this)) {
886                LOC_LOGE("Error: Could not start delay thread\n");
887                ret = -1;
888                goto err;
889            }
890        }
891        break;
892    case LOC_API_ADAPTER_ERR_UNSUPPORTED:
893        LOC_LOGE("No profile found for emergency call. Fallback to normal SUPL ATL\n");
894        informStatus(RSRC_DENIED, connHandle);
895        break;
896    case LOC_API_ADAPTER_ERR_SUCCESS:
897        LOC_LOGD("%s:%d]: Request to start data call sent\n", __func__, __LINE__);
898        break;
899    case -1:
900        //One of the ways this case can be encountered is if the callback function
901        //receives a null argument, it just exits with -1 error
902        LOC_LOGE("Error: Something went wrong somewhere. Falling back to normal SUPL ATL\n");
903        informStatus(RSRC_DENIED, connHandle);
904        break;
905    default:
906        LOC_LOGE("%s:%d]: Unrecognized return value\n", __func__, __LINE__);
907    }
908err:
909    LOC_LOGD("EXIT DSStateMachine :: sendRsrcRequest; ret = %d\n", ret);
910    return ret;
911}
912
913void DSStateMachine :: onRsrcEvent(AgpsRsrcStatus event)
914{
915    void* currState = (void *)mStatePtr;
916    LOC_LOGD("Enter DSStateMachine :: onRsrcEvent. event = %d\n", (int)event);
917    switch (event)
918    {
919    case RSRC_GRANTED:
920        LOC_LOGD("DSStateMachine :: onRsrcEvent RSRC_GRANTED\n");
921        mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
922        break;
923    case RSRC_RELEASED:
924        LOC_LOGD("DSStateMachine :: onRsrcEvent RSRC_RELEASED\n");
925        mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
926        //To handle the case where we get a RSRC_RELEASED in
927        //pending state, we translate that to a RSRC_DENIED state
928        //since the callback from DSI is either RSRC_GRANTED or RSRC_RELEASED
929        //for when the call is connected or disconnected respectively.
930        if((void *)mStatePtr != currState)
931            break;
932        else {
933            event = RSRC_DENIED;
934            LOC_LOGE(" Switching event to RSRC_DENIED\n");
935        }
936    case RSRC_DENIED:
937        mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
938        break;
939    default:
940        LOC_LOGW("AgpsStateMachine: unrecognized event %d", event);
941        break;
942    }
943    LOC_LOGD("Exit DSStateMachine :: onRsrcEvent. event = %d\n", (int)event);
944}
945
946void DSStateMachine :: informStatus(AgpsRsrcStatus status, int ID) const
947{
948    LOC_LOGD("DSStateMachine :: informStatus. Status=%d\n",(int)status);
949    switch(status) {
950    case RSRC_UNSUBSCRIBE:
951        mLocAdapter->atlCloseStatus(ID, 1);
952        break;
953    case RSRC_RELEASED:
954        mLocAdapter->closeDataCall();
955        break;
956    case RSRC_DENIED:
957        ((DSStateMachine *)this)->mRetries = 0;
958        mLocAdapter->requestATL(ID, AGPS_TYPE_SUPL);
959        break;
960    case RSRC_GRANTED:
961        mLocAdapter->atlOpenStatus(ID, 1,
962                                                     NULL,
963                                                     AGPS_APN_BEARER_INVALID,
964                                                     AGPS_TYPE_INVALID);
965        break;
966    default:
967        LOC_LOGW("DSStateMachine :: informStatus - unknown status");
968    }
969    return;
970}
971