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 ¬ification)
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 ¬ification)
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 ¬ification)
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 ¬ification)
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 ¬ification)
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*)¬ification, 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*)¬ification, 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*)¬ification, 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*)¬ification, 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(¬ification, 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*)¬ification, 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*)¬ification, 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*)¬ification, 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*)¬ification, 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