• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
deleteObj(void * data)47 static 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
hasSubscriber(void * fromCaller,void * fromList)56 static 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
notifySubscriber(void * fromCaller,void * fromList)69 static 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 //======================================================================
86 const int Notification::BROADCAST_ALL = 0x80000000;
87 const int Notification::BROADCAST_ACTIVE = 0x80000001;
88 const int Notification::BROADCAST_INACTIVE = 0x80000002;
89 const unsigned char DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4;
90 const unsigned int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500;
91 //======================================================================
92 // Subscriber:  BITSubscriber / ATLSubscriber / WIFISubscriber
93 //======================================================================
forMe(Notification & notification)94 bool 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 }
equals(const Subscriber * s) const106 bool 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 
notifyRsrcStatus(Notification & notification)115 bool 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 
notifyRsrcStatus(Notification & notification)146 bool 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 
notifyRsrcStatus(Notification & notification)185 bool 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 }
notifyRsrcStatus(Notification & notification)216 bool 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 }
setInactive()234 void DSSubscriber :: setInactive()
235 {
236     mIsInactive = true;
237     ((DSStateMachine *)mStateMachine)->informStatus(RSRC_UNSUBSCRIBE, ID);
238 }
239 //======================================================================
240 // AgpsState:  AgpsReleasedState / AgpsPendingState / AgpsAcquiredState
241 //======================================================================
242 
243 // AgpsReleasedState
244 class AgpsReleasedState : public AgpsState
245 {
246     friend class AgpsStateMachine;
247 
AgpsReleasedState(AgpsStateMachine * stateMachine)248     inline AgpsReleasedState(AgpsStateMachine* stateMachine) :
249         AgpsState(stateMachine)
250     { mReleasedState = this; }
251 
~AgpsReleasedState()252     inline ~AgpsReleasedState() {}
253 public:
254     virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
whoami()255     inline virtual char* whoami() {return (char*)"AgpsReleasedState";}
256 };
257 
onRsrcEvent(AgpsRsrcStatus event,void * data)258 AgpsState* 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
311 class AgpsPendingState : public AgpsState
312 {
313     friend class AgpsStateMachine;
314 
AgpsPendingState(AgpsStateMachine * stateMachine)315     inline AgpsPendingState(AgpsStateMachine* stateMachine) :
316         AgpsState(stateMachine)
317     { mPendingState = this; }
318 
~AgpsPendingState()319     inline ~AgpsPendingState() {}
320 public:
321     virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
whoami()322     inline virtual char* whoami() {return (char*)"AgpsPendingState";}
323 };
324 
onRsrcEvent(AgpsRsrcStatus event,void * data)325 AgpsState* 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 
406 class AgpsAcquiredState : public AgpsState
407 {
408     friend class AgpsStateMachine;
409 
AgpsAcquiredState(AgpsStateMachine * stateMachine)410     inline AgpsAcquiredState(AgpsStateMachine* stateMachine) :
411         AgpsState(stateMachine)
412     { mAcquiredState = this; }
413 
~AgpsAcquiredState()414     inline ~AgpsAcquiredState() {}
415 public:
416     virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
whoami()417     inline virtual char* whoami() { return (char*)"AgpsAcquiredState"; }
418 };
419 
420 
onRsrcEvent(AgpsRsrcStatus event,void * data)421 AgpsState* 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
500 class AgpsReleasingState : public AgpsState
501 {
502     friend class AgpsStateMachine;
503 
AgpsReleasingState(AgpsStateMachine * stateMachine)504     inline AgpsReleasingState(AgpsStateMachine* stateMachine) :
505         AgpsState(stateMachine)
506     { mReleasingState = this; }
507 
~AgpsReleasingState()508     inline ~AgpsReleasingState() {}
509 public:
510     virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
whoami()511     inline virtual char* whoami() {return (char*)"AgpsReleasingState";}
512 };
513 
onRsrcEvent(AgpsRsrcStatus event,void * data)514 AgpsState* 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 //======================================================================
getServicer(servicerType type,void * cb_func)583 Servicer* 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 
requestRsrc(void * cb_data)598 int Servicer :: requestRsrc(void *cb_data)
599 {
600     callback();
601     return 0;
602 }
603 
requestRsrc(void * cb_data)604 int 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 
requestRsrc(void * cb_data)613 int AGpsServicer :: requestRsrc(void *cb_data)
614 {
615     callbackAGps((AGpsStatus *)cb_data);
616     return 0;
617 }
618 
619 //======================================================================
620 // AgpsStateMachine
621 //======================================================================
622 
AgpsStateMachine(servicerType servType,void * cb_func,AGpsExtType type,bool enforceSingleSubscriber)623 AgpsStateMachine::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 
~AgpsStateMachine()657 AgpsStateMachine::~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 
setAPN(const char * apn,unsigned int len)682 void 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 
onRsrcEvent(AgpsRsrcStatus event)700 void 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 
notifySubscribers(Notification & notification) const715 void 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 
addSubscriber(Subscriber * subscriber) const738 void 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 
sendRsrcRequest(AGpsStatusValue action) const750 int 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             memset(&nifRequest.addr, 0,  sizeof(nifRequest.addr));
766             nifRequest.ssid[0] = '\0';
767             nifRequest.password[0] = '\0';
768         } else {
769             s->setIPAddresses(nifRequest.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 
subscribeRsrc(Subscriber * subscriber)779 void 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 
unsubscribeRsrc(Subscriber * subscriber)789 bool 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 
hasActiveSubscribers() const803 bool 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 //======================================================================
delay_callback(void * callbackData,int result)815 void 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     }
825 err:
826     return;
827 }
828 
DSStateMachine(servicerType type,void * cb_func,LocEngAdapter * adapterHandle)829 DSStateMachine :: 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 
retryCallback(void)838 void 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 
sendRsrcRequest(AGpsStatusValue action) const852 int 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     }
908 err:
909     LOC_LOGD("EXIT DSStateMachine :: sendRsrcRequest; ret = %d\n", ret);
910     return ret;
911 }
912 
onRsrcEvent(AgpsRsrcStatus event)913 void 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 
informStatus(AgpsRsrcStatus status,int ID) const946 void 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