1 /* Copyright (c) 2012-2017, 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 #define LOG_NDEBUG 0
30 #define LOG_TAG "LocSvc_Agps"
31
32 #include <Agps.h>
33 #include <loc_pla.h>
34 #include <ContextBase.h>
35 #include <loc_timer.h>
36 #include <inttypes.h>
37
38 /* --------------------------------------------------------------------
39 * AGPS State Machine Methods
40 * -------------------------------------------------------------------*/
processAgpsEvent(AgpsEvent event)41 void AgpsStateMachine::processAgpsEvent(AgpsEvent event){
42
43 LOC_LOGD("processAgpsEvent(): SM %p, Event %d, State %d",
44 this, event, mState);
45
46 switch (event) {
47
48 case AGPS_EVENT_SUBSCRIBE:
49 processAgpsEventSubscribe();
50 break;
51
52 case AGPS_EVENT_UNSUBSCRIBE:
53 processAgpsEventUnsubscribe();
54 break;
55
56 case AGPS_EVENT_GRANTED:
57 processAgpsEventGranted();
58 break;
59
60 case AGPS_EVENT_RELEASED:
61 processAgpsEventReleased();
62 break;
63
64 case AGPS_EVENT_DENIED:
65 processAgpsEventDenied();
66 break;
67
68 default:
69 LOC_LOGE("Invalid Loc Agps Event");
70 }
71 }
72
processAgpsEventSubscribe()73 void AgpsStateMachine::processAgpsEventSubscribe(){
74
75 switch (mState) {
76
77 case AGPS_STATE_RELEASED:
78 /* Add subscriber to list
79 * No notifications until we get RSRC_GRANTED */
80 addSubscriber(mCurrentSubscriber);
81
82 /* Send data request
83 * The if condition below is added so that if the data call setup
84 * fails for DS State Machine, we want to retry in released state.
85 * for Agps State Machine, sendRsrcRequest() will always return
86 * success. */
87 if (requestOrReleaseDataConn(true) == 0) {
88 // If data request successful, move to pending state
89 transitionState(AGPS_STATE_PENDING);
90 }
91 break;
92
93 case AGPS_STATE_PENDING:
94 /* Already requested for data connection,
95 * do nothing until we get RSRC_GRANTED event;
96 * Just add this subscriber to the list, for notifications */
97 addSubscriber(mCurrentSubscriber);
98 break;
99
100 case AGPS_STATE_ACQUIRED:
101 /* We already have the data connection setup,
102 * Notify current subscriber with GRANTED event,
103 * And add it to the subscriber list for further notifications. */
104 notifyEventToSubscriber(AGPS_EVENT_GRANTED, mCurrentSubscriber, false);
105 addSubscriber(mCurrentSubscriber);
106 break;
107
108 case AGPS_STATE_RELEASING:
109 addSubscriber(mCurrentSubscriber);
110 break;
111
112 default:
113 LOC_LOGE("Invalid state: %d", mState);
114 }
115 }
116
processAgpsEventUnsubscribe()117 void AgpsStateMachine::processAgpsEventUnsubscribe(){
118
119 switch (mState) {
120
121 case AGPS_STATE_RELEASED:
122 notifyEventToSubscriber(
123 AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, false);
124 break;
125
126 case AGPS_STATE_PENDING:
127 case AGPS_STATE_ACQUIRED:
128 /* If the subscriber wishes to wait for connection close,
129 * before being removed from list, move to inactive state
130 * and notify */
131 if (mCurrentSubscriber->mWaitForCloseComplete) {
132 mCurrentSubscriber->mIsInactive = true;
133 }
134 else {
135 /* Notify only current subscriber and then delete it from
136 * subscriberList */
137 notifyEventToSubscriber(
138 AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, true);
139 }
140
141 /* If no subscribers in list, release data connection */
142 if (mSubscriberList.empty()) {
143 transitionState(AGPS_STATE_RELEASED);
144 requestOrReleaseDataConn(false);
145 }
146 /* Some subscribers in list, but all inactive;
147 * Release data connection */
148 else if(!anyActiveSubscribers()) {
149 transitionState(AGPS_STATE_RELEASING);
150 requestOrReleaseDataConn(false);
151 }
152 break;
153
154 case AGPS_STATE_RELEASING:
155 /* If the subscriber wishes to wait for connection close,
156 * before being removed from list, move to inactive state
157 * and notify */
158 if (mCurrentSubscriber->mWaitForCloseComplete) {
159 mCurrentSubscriber->mIsInactive = true;
160 }
161 else {
162 /* Notify only current subscriber and then delete it from
163 * subscriberList */
164 notifyEventToSubscriber(
165 AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, true);
166 }
167
168 /* If no subscribers in list, just move the state.
169 * Request for releasing data connection should already have been
170 * sent */
171 if (mSubscriberList.empty()) {
172 transitionState(AGPS_STATE_RELEASED);
173 }
174 break;
175
176 default:
177 LOC_LOGE("Invalid state: %d", mState);
178 }
179 }
180
processAgpsEventGranted()181 void AgpsStateMachine::processAgpsEventGranted(){
182
183 switch (mState) {
184
185 case AGPS_STATE_RELEASED:
186 case AGPS_STATE_ACQUIRED:
187 case AGPS_STATE_RELEASING:
188 LOC_LOGE("Unexpected event GRANTED in state %d", mState);
189 break;
190
191 case AGPS_STATE_PENDING:
192 // Move to acquired state
193 transitionState(AGPS_STATE_ACQUIRED);
194 notifyAllSubscribers(
195 AGPS_EVENT_GRANTED, false,
196 AGPS_NOTIFICATION_TYPE_FOR_ACTIVE_SUBSCRIBERS);
197 break;
198
199 default:
200 LOC_LOGE("Invalid state: %d", mState);
201 }
202 }
203
processAgpsEventReleased()204 void AgpsStateMachine::processAgpsEventReleased(){
205
206 switch (mState) {
207
208 case AGPS_STATE_RELEASED:
209 /* Subscriber list should be empty if we are in released state */
210 if (!mSubscriberList.empty()) {
211 LOC_LOGE("Unexpected event RELEASED in RELEASED state");
212 }
213 break;
214
215 case AGPS_STATE_ACQUIRED:
216 /* Force release received */
217 LOC_LOGW("Force RELEASED event in ACQUIRED state");
218 transitionState(AGPS_STATE_RELEASED);
219 notifyAllSubscribers(
220 AGPS_EVENT_RELEASED, true,
221 AGPS_NOTIFICATION_TYPE_FOR_ALL_SUBSCRIBERS);
222 break;
223
224 case AGPS_STATE_RELEASING:
225 /* Notify all inactive subscribers about the event */
226 notifyAllSubscribers(
227 AGPS_EVENT_RELEASED, true,
228 AGPS_NOTIFICATION_TYPE_FOR_INACTIVE_SUBSCRIBERS);
229
230 /* If we have active subscribers now, they must be waiting for
231 * data conn setup */
232 if (anyActiveSubscribers()) {
233 transitionState(AGPS_STATE_PENDING);
234 requestOrReleaseDataConn(true);
235 }
236 /* No active subscribers, move to released state */
237 else {
238 transitionState(AGPS_STATE_RELEASED);
239 }
240 break;
241
242 case AGPS_STATE_PENDING:
243 /* NOOP */
244 break;
245
246 default:
247 LOC_LOGE("Invalid state: %d", mState);
248 }
249 }
250
processAgpsEventDenied()251 void AgpsStateMachine::processAgpsEventDenied(){
252
253 switch (mState) {
254
255 case AGPS_STATE_RELEASED:
256 LOC_LOGE("Unexpected event DENIED in state %d", mState);
257 break;
258
259 case AGPS_STATE_ACQUIRED:
260 /* NOOP */
261 break;
262
263 case AGPS_STATE_RELEASING:
264 /* Notify all inactive subscribers about the event */
265 notifyAllSubscribers(
266 AGPS_EVENT_RELEASED, true,
267 AGPS_NOTIFICATION_TYPE_FOR_INACTIVE_SUBSCRIBERS);
268
269 /* If we have active subscribers now, they must be waiting for
270 * data conn setup */
271 if (anyActiveSubscribers()) {
272 transitionState(AGPS_STATE_PENDING);
273 requestOrReleaseDataConn(true);
274 }
275 /* No active subscribers, move to released state */
276 else {
277 transitionState(AGPS_STATE_RELEASED);
278 }
279 break;
280
281 case AGPS_STATE_PENDING:
282 transitionState(AGPS_STATE_RELEASED);
283 notifyAllSubscribers(
284 AGPS_EVENT_DENIED, true,
285 AGPS_NOTIFICATION_TYPE_FOR_ALL_SUBSCRIBERS);
286 break;
287
288 default:
289 LOC_LOGE("Invalid state: %d", mState);
290 }
291 }
292
293 /* Request or Release data connection
294 * bool request :
295 * true = Request data connection
296 * false = Release data connection */
requestOrReleaseDataConn(bool request)297 int AgpsStateMachine::requestOrReleaseDataConn(bool request){
298
299 AGnssExtStatusIpV4 nifRequest;
300 memset(&nifRequest, 0, sizeof(nifRequest));
301
302 nifRequest.type = mAgpsType;
303
304 if (request) {
305 LOC_LOGD("AGPS Data Conn Request");
306 nifRequest.status = LOC_GPS_REQUEST_AGPS_DATA_CONN;
307 }
308 else{
309 LOC_LOGD("AGPS Data Conn Release");
310 nifRequest.status = LOC_GPS_RELEASE_AGPS_DATA_CONN;
311 }
312
313 mAgpsManager->mFrameworkStatusV4Cb(nifRequest);
314 return 0;
315 }
316
notifyAllSubscribers(AgpsEvent event,bool deleteSubscriberPostNotify,AgpsNotificationType notificationType)317 void AgpsStateMachine::notifyAllSubscribers(
318 AgpsEvent event, bool deleteSubscriberPostNotify,
319 AgpsNotificationType notificationType){
320
321 LOC_LOGD("notifyAllSubscribers(): "
322 "SM %p, Event %d Delete %d Notification Type %d",
323 this, event, deleteSubscriberPostNotify, notificationType);
324
325 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
326 while ( it != mSubscriberList.end() ) {
327
328 AgpsSubscriber* subscriber = *it;
329
330 if (notificationType == AGPS_NOTIFICATION_TYPE_FOR_ALL_SUBSCRIBERS ||
331 (notificationType == AGPS_NOTIFICATION_TYPE_FOR_INACTIVE_SUBSCRIBERS &&
332 subscriber->mIsInactive) ||
333 (notificationType == AGPS_NOTIFICATION_TYPE_FOR_ACTIVE_SUBSCRIBERS &&
334 !subscriber->mIsInactive)) {
335
336 /* Deleting via this call would require another traversal
337 * through subscriber list, inefficient; hence pass in false*/
338 notifyEventToSubscriber(event, subscriber, false);
339
340 if (deleteSubscriberPostNotify) {
341 it = mSubscriberList.erase(it);
342 delete subscriber;
343 } else {
344 it++;
345 }
346 } else {
347 it++;
348 }
349 }
350 }
351
notifyEventToSubscriber(AgpsEvent event,AgpsSubscriber * subscriberToNotify,bool deleteSubscriberPostNotify)352 void AgpsStateMachine::notifyEventToSubscriber(
353 AgpsEvent event, AgpsSubscriber* subscriberToNotify,
354 bool deleteSubscriberPostNotify) {
355
356 LOC_LOGD("notifyEventToSubscriber(): "
357 "SM %p, Event %d Subscriber %p Delete %d",
358 this, event, subscriberToNotify, deleteSubscriberPostNotify);
359
360 switch (event) {
361
362 case AGPS_EVENT_GRANTED:
363 mAgpsManager->mAtlOpenStatusCb(
364 subscriberToNotify->mConnHandle, 1, getAPN(),
365 getBearer(), mAgpsType, LOC_APN_TYPE_MASK_SUPL);
366 break;
367
368 case AGPS_EVENT_DENIED:
369 mAgpsManager->mAtlOpenStatusCb(
370 subscriberToNotify->mConnHandle, 0, getAPN(),
371 getBearer(), mAgpsType, LOC_APN_TYPE_MASK_SUPL);
372 break;
373
374 case AGPS_EVENT_UNSUBSCRIBE:
375 case AGPS_EVENT_RELEASED:
376 mAgpsManager->mAtlCloseStatusCb(subscriberToNotify->mConnHandle, 1);
377 break;
378
379 default:
380 LOC_LOGE("Invalid event %d", event);
381 }
382
383 /* Search this subscriber in list and delete */
384 if (deleteSubscriberPostNotify) {
385 deleteSubscriber(subscriberToNotify);
386 }
387 }
388
transitionState(AgpsState newState)389 void AgpsStateMachine::transitionState(AgpsState newState){
390
391 LOC_LOGD("transitionState(): SM %p, old %d, new %d",
392 this, mState, newState);
393
394 mState = newState;
395
396 // notify state transitions to all subscribers ?
397 }
398
addSubscriber(AgpsSubscriber * subscriberToAdd)399 void AgpsStateMachine::addSubscriber(AgpsSubscriber* subscriberToAdd){
400
401 LOC_LOGD("addSubscriber(): SM %p, Subscriber %p",
402 this, subscriberToAdd);
403
404 // Check if subscriber is already present in the current list
405 // If not, then add
406 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
407 for (; it != mSubscriberList.end(); it++) {
408 AgpsSubscriber* subscriber = *it;
409 if (subscriber->equals(subscriberToAdd)) {
410 LOC_LOGE("Subscriber already in list");
411 return;
412 }
413 }
414
415 AgpsSubscriber* cloned = subscriberToAdd->clone();
416 LOC_LOGD("addSubscriber(): cloned subscriber: %p", cloned);
417 mSubscriberList.push_back(cloned);
418 }
419
deleteSubscriber(AgpsSubscriber * subscriberToDelete)420 void AgpsStateMachine::deleteSubscriber(AgpsSubscriber* subscriberToDelete){
421
422 LOC_LOGD("deleteSubscriber(): SM %p, Subscriber %p",
423 this, subscriberToDelete);
424
425 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
426 while ( it != mSubscriberList.end() ) {
427
428 AgpsSubscriber* subscriber = *it;
429 if (subscriber && subscriber->equals(subscriberToDelete)) {
430
431 it = mSubscriberList.erase(it);
432 delete subscriber;
433 } else {
434 it++;
435 }
436 }
437 }
438
anyActiveSubscribers()439 bool AgpsStateMachine::anyActiveSubscribers(){
440
441 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
442 for (; it != mSubscriberList.end(); it++) {
443 AgpsSubscriber* subscriber = *it;
444 if (!subscriber->mIsInactive) {
445 return true;
446 }
447 }
448 return false;
449 }
450
setAPN(char * apn,unsigned int len)451 void AgpsStateMachine::setAPN(char* apn, unsigned int len){
452
453 if (NULL != mAPN) {
454 delete mAPN;
455 mAPN = NULL;
456 }
457
458 if (NULL == apn || len <= 0 || len > MAX_APN_LEN || strlen(apn) != len) {
459 LOC_LOGD("Invalid apn len (%d) or null apn", len);
460 mAPN = NULL;
461 mAPNLen = 0;
462 } else {
463 mAPN = new char[len+1];
464 if (NULL != mAPN) {
465 memcpy(mAPN, apn, len);
466 mAPN[len] = '\0';
467 mAPNLen = len;
468 }
469 }
470 }
471
getSubscriber(int connHandle)472 AgpsSubscriber* AgpsStateMachine::getSubscriber(int connHandle){
473
474 /* Go over the subscriber list */
475 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
476 for (; it != mSubscriberList.end(); it++) {
477 AgpsSubscriber* subscriber = *it;
478 if (subscriber->mConnHandle == connHandle) {
479 return subscriber;
480 }
481 }
482
483 /* Not found, return NULL */
484 return NULL;
485 }
486
getFirstSubscriber(bool isInactive)487 AgpsSubscriber* AgpsStateMachine::getFirstSubscriber(bool isInactive){
488
489 /* Go over the subscriber list */
490 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
491 for (; it != mSubscriberList.end(); it++) {
492 AgpsSubscriber* subscriber = *it;
493 if(subscriber->mIsInactive == isInactive) {
494 return subscriber;
495 }
496 }
497
498 /* Not found, return NULL */
499 return NULL;
500 }
501
dropAllSubscribers()502 void AgpsStateMachine::dropAllSubscribers(){
503
504 LOC_LOGD("dropAllSubscribers(): SM %p", this);
505
506 /* Go over the subscriber list */
507 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
508 while ( it != mSubscriberList.end() ) {
509 AgpsSubscriber* subscriber = *it;
510 it = mSubscriberList.erase(it);
511 delete subscriber;
512 }
513 }
514
515 /* --------------------------------------------------------------------
516 * DS State Machine Methods
517 * -------------------------------------------------------------------*/
518 const int DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4;
519 const int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500;
520
521 /* Overridden method
522 * DS SM needs to handle one scenario differently */
processAgpsEvent(AgpsEvent event)523 void DSStateMachine::processAgpsEvent(AgpsEvent event) {
524
525 LOC_LOGD("DSStateMachine::processAgpsEvent() %d", event);
526
527 /* DS Client call setup APIs don't return failure/closure separately.
528 * Hence we receive RELEASED event in both cases.
529 * If we are in pending, we should consider RELEASED as DENIED */
530 if (event == AGPS_EVENT_RELEASED && mState == AGPS_STATE_PENDING) {
531
532 LOC_LOGD("Translating RELEASED to DENIED event");
533 event = AGPS_EVENT_DENIED;
534 }
535
536 /* Redirect process to base class */
537 AgpsStateMachine::processAgpsEvent(event);
538 }
539
540 /* Timer Callback
541 * For the retry timer started in case of DS Client call setup failure */
delay_callback(void * callbackData,int result)542 void delay_callback(void *callbackData, int result)
543 {
544 LOC_LOGD("delay_callback(): cbData %p", callbackData);
545
546 (void)result;
547
548 if (callbackData == NULL) {
549 LOC_LOGE("delay_callback(): NULL argument received !");
550 return;
551 }
552 DSStateMachine* dsStateMachine = (DSStateMachine *)callbackData;
553 dsStateMachine->retryCallback();
554 }
555
556 /* Invoked from Timer Callback
557 * For the retry timer started in case of DS Client call setup failure */
retryCallback()558 void DSStateMachine :: retryCallback()
559 {
560 LOC_LOGD("DSStateMachine::retryCallback()");
561
562 /* Request SUPL ES
563 * There must be at least one active subscriber in list */
564 AgpsSubscriber* subscriber = getFirstSubscriber(false);
565 if (subscriber == NULL) {
566
567 LOC_LOGE("No active subscriber for DS Client call setup");
568 return;
569 }
570
571 /* Send message to retry */
572 mAgpsManager->mSendMsgToAdapterQueueFn(
573 new AgpsMsgRequestATL(
574 mAgpsManager, subscriber->mConnHandle,
575 LOC_AGPS_TYPE_SUPL_ES, subscriber->mApnTypeMask));
576 }
577
578 /* Overridden method
579 * Request or Release data connection
580 * bool request :
581 * true = Request data connection
582 * false = Release data connection */
requestOrReleaseDataConn(bool request)583 int DSStateMachine::requestOrReleaseDataConn(bool request){
584
585 LOC_LOGD("DSStateMachine::requestOrReleaseDataConn(): "
586 "request %d", request);
587
588 /* Release data connection required ? */
589 if (!request && mAgpsManager->mDSClientStopDataCallFn) {
590
591 mAgpsManager->mDSClientStopDataCallFn();
592 LOC_LOGD("DS Client release data call request sent !");
593 return 0;
594 }
595
596 /* Setup data connection request
597 * There must be at least one active subscriber in list */
598 AgpsSubscriber* subscriber = getFirstSubscriber(false);
599 if (subscriber == NULL) {
600
601 LOC_LOGE("No active subscriber for DS Client call setup");
602 return -1;
603 }
604
605 /* DS Client Fn registered ? */
606 if (!mAgpsManager->mDSClientOpenAndStartDataCallFn) {
607
608 LOC_LOGE("DS Client start fn not registered, fallback to SUPL ATL");
609 notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false);
610 return -1;
611 }
612
613 /* Setup the call */
614 int ret = mAgpsManager->mDSClientOpenAndStartDataCallFn();
615
616 /* Check if data call start failed */
617 switch (ret) {
618
619 case LOC_API_ADAPTER_ERR_ENGINE_BUSY:
620 LOC_LOGE("DS Client open call failed, err: %d", ret);
621 mRetries++;
622 if (mRetries > MAX_START_DATA_CALL_RETRIES) {
623
624 LOC_LOGE("DS Client call retries exhausted, "
625 "falling back to normal SUPL ATL");
626 notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false);
627 }
628 /* Retry DS Client call setup after some delay */
629 else if(loc_timer_start(
630 DATA_CALL_RETRY_DELAY_MSEC, delay_callback, this)) {
631 LOC_LOGE("Error: Could not start delay thread\n");
632 return -1;
633 }
634 break;
635
636 case LOC_API_ADAPTER_ERR_UNSUPPORTED:
637 LOC_LOGE("No emergency profile found. Fall back to normal SUPL ATL");
638 notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false);
639 break;
640
641 case LOC_API_ADAPTER_ERR_SUCCESS:
642 LOC_LOGD("Request to start data call sent");
643 break;
644
645 default:
646 LOC_LOGE("Unrecognized return value: %d", ret);
647 }
648
649 return ret;
650 }
651
notifyEventToSubscriber(AgpsEvent event,AgpsSubscriber * subscriberToNotify,bool deleteSubscriberPostNotify)652 void DSStateMachine::notifyEventToSubscriber(
653 AgpsEvent event, AgpsSubscriber* subscriberToNotify,
654 bool deleteSubscriberPostNotify) {
655
656 LOC_LOGD("DSStateMachine::notifyEventToSubscriber(): "
657 "SM %p, Event %d Subscriber %p Delete %d",
658 this, event, subscriberToNotify, deleteSubscriberPostNotify);
659
660 switch (event) {
661
662 case AGPS_EVENT_GRANTED:
663 mAgpsManager->mAtlOpenStatusCb(
664 subscriberToNotify->mConnHandle, 1, NULL,
665 AGPS_APN_BEARER_INVALID, LOC_AGPS_TYPE_SUPL_ES,
666 LOC_APN_TYPE_MASK_EMERGENCY);
667 break;
668
669 case AGPS_EVENT_DENIED:
670 /* Now try with regular SUPL
671 * We need to send request via message queue */
672 mRetries = 0;
673 mAgpsManager->mSendMsgToAdapterQueueFn(
674 new AgpsMsgRequestATL(
675 mAgpsManager, subscriberToNotify->mConnHandle,
676 LOC_AGPS_TYPE_SUPL, subscriberToNotify->mApnTypeMask));
677 break;
678
679 case AGPS_EVENT_UNSUBSCRIBE:
680 mAgpsManager->mAtlCloseStatusCb(subscriberToNotify->mConnHandle, 1);
681 break;
682
683 case AGPS_EVENT_RELEASED:
684 mAgpsManager->mDSClientCloseDataCallFn();
685 mAgpsManager->mAtlCloseStatusCb(subscriberToNotify->mConnHandle, 1);
686 break;
687
688 default:
689 LOC_LOGE("Invalid event %d", event);
690 }
691
692 /* Search this subscriber in list and delete */
693 if (deleteSubscriberPostNotify) {
694 deleteSubscriber(subscriberToNotify);
695 }
696 }
697
698 /* --------------------------------------------------------------------
699 * Loc AGPS Manager Methods
700 * -------------------------------------------------------------------*/
701
702 /* CREATE AGPS STATE MACHINES
703 * Must be invoked in Msg Handler context */
createAgpsStateMachines()704 void AgpsManager::createAgpsStateMachines() {
705
706 LOC_LOGD("AgpsManager::createAgpsStateMachines");
707
708 bool agpsCapable =
709 ((loc_core::ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA) ||
710 (loc_core::ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB));
711
712 if (NULL == mInternetNif) {
713 mInternetNif = new AgpsStateMachine(this, LOC_AGPS_TYPE_WWAN_ANY);
714 LOC_LOGD("Internet NIF: %p", mInternetNif);
715 }
716 if (agpsCapable) {
717 if (NULL == mAgnssNif) {
718 mAgnssNif = new AgpsStateMachine(this, LOC_AGPS_TYPE_SUPL);
719 LOC_LOGD("AGNSS NIF: %p", mAgnssNif);
720 }
721 if (NULL == mDsNif &&
722 loc_core::ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
723
724 if(!mDSClientInitFn){
725
726 LOC_LOGE("DS Client Init Fn not registered !");
727 return;
728 }
729 if (mDSClientInitFn(false) != 0) {
730
731 LOC_LOGE("Failed to init data service client");
732 return;
733 }
734 mDsNif = new DSStateMachine(this);
735 LOC_LOGD("DS NIF: %p", mDsNif);
736 }
737 }
738 }
739
getAgpsStateMachine(AGpsExtType agpsType)740 AgpsStateMachine* AgpsManager::getAgpsStateMachine(AGpsExtType agpsType) {
741
742 LOC_LOGD("AgpsManager::getAgpsStateMachine(): agpsType %d", agpsType);
743
744 switch (agpsType) {
745
746 case LOC_AGPS_TYPE_INVALID:
747 case LOC_AGPS_TYPE_SUPL:
748 if (mAgnssNif == NULL) {
749 LOC_LOGE("NULL AGNSS NIF !");
750 }
751 return mAgnssNif;
752
753 case LOC_AGPS_TYPE_SUPL_ES:
754 if (loc_core::ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
755 if (mDsNif == NULL) {
756 createAgpsStateMachines();
757 }
758 return mDsNif;
759 } else {
760 return mAgnssNif;
761 }
762
763 default:
764 return mInternetNif;
765 }
766
767 LOC_LOGE("No SM found !");
768 return NULL;
769 }
770
requestATL(int connHandle,AGpsExtType agpsType,LocApnTypeMask mask)771 void AgpsManager::requestATL(int connHandle, AGpsExtType agpsType, LocApnTypeMask mask){
772
773 LOC_LOGD("AgpsManager::requestATL(): connHandle %d, agpsType %d apnTypeMask %" PRIu64,
774 connHandle, agpsType, mask);
775
776 AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
777
778 if (sm == NULL) {
779
780 LOC_LOGE("No AGPS State Machine for agpsType: %d", agpsType);
781 mAtlOpenStatusCb(
782 connHandle, 0, NULL, AGPS_APN_BEARER_INVALID, agpsType, mask);
783 return;
784 }
785
786 /* Invoke AGPS SM processing */
787 AgpsSubscriber subscriber(connHandle, false, false, mask);
788 sm->setCurrentSubscriber(&subscriber);
789
790 /* If DS State Machine, wait for close complete */
791 if (agpsType == LOC_AGPS_TYPE_SUPL_ES) {
792 subscriber.mWaitForCloseComplete = true;
793 }
794
795 /* Send subscriber event */
796 sm->processAgpsEvent(AGPS_EVENT_SUBSCRIBE);
797 }
798
releaseATL(int connHandle)799 void AgpsManager::releaseATL(int connHandle){
800
801 LOC_LOGD("AgpsManager::releaseATL(): connHandle %d", connHandle);
802
803 /* First find the subscriber with specified handle.
804 * We need to search in all state machines. */
805 AgpsStateMachine* sm = NULL;
806 AgpsSubscriber* subscriber = NULL;
807
808 if (mAgnssNif &&
809 (subscriber = mAgnssNif->getSubscriber(connHandle)) != NULL) {
810 sm = mAgnssNif;
811 }
812 else if (mInternetNif &&
813 (subscriber = mInternetNif->getSubscriber(connHandle)) != NULL) {
814 sm = mInternetNif;
815 }
816 else if (mDsNif &&
817 (subscriber = mDsNif->getSubscriber(connHandle)) != NULL) {
818 sm = mDsNif;
819 }
820
821 if (sm == NULL) {
822 LOC_LOGE("Subscriber with connHandle %d not found in any SM",
823 connHandle);
824 mAtlCloseStatusCb(connHandle, 0);
825 return;
826 }
827
828 /* Now send unsubscribe event */
829 sm->setCurrentSubscriber(subscriber);
830 sm->processAgpsEvent(AGPS_EVENT_UNSUBSCRIBE);
831 }
832
reportDataCallOpened()833 void AgpsManager::reportDataCallOpened(){
834
835 LOC_LOGD("AgpsManager::reportDataCallOpened");
836
837 if (mDsNif) {
838 mDsNif->processAgpsEvent(AGPS_EVENT_GRANTED);
839 }
840 }
841
reportDataCallClosed()842 void AgpsManager::reportDataCallClosed(){
843
844 LOC_LOGD("AgpsManager::reportDataCallClosed");
845
846 if (mDsNif) {
847 mDsNif->processAgpsEvent(AGPS_EVENT_RELEASED);
848 }
849 }
850
reportAtlOpenSuccess(AGpsExtType agpsType,char * apnName,int apnLen,AGpsBearerType bearerType)851 void AgpsManager::reportAtlOpenSuccess(
852 AGpsExtType agpsType, char* apnName, int apnLen,
853 AGpsBearerType bearerType){
854
855 LOC_LOGD("AgpsManager::reportAtlOpenSuccess(): "
856 "AgpsType %d, APN [%s], Len %d, BearerType %d",
857 agpsType, apnName, apnLen, bearerType);
858
859 /* Find the state machine instance */
860 AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
861
862 /* Set bearer and apn info in state machine instance */
863 sm->setBearer(bearerType);
864 sm->setAPN(apnName, apnLen);
865
866 /* Send GRANTED event to state machine */
867 sm->processAgpsEvent(AGPS_EVENT_GRANTED);
868 }
869
reportAtlOpenFailed(AGpsExtType agpsType)870 void AgpsManager::reportAtlOpenFailed(AGpsExtType agpsType){
871
872 LOC_LOGD("AgpsManager::reportAtlOpenFailed(): AgpsType %d", agpsType);
873
874 /* Fetch SM and send DENIED event */
875 AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
876 sm->processAgpsEvent(AGPS_EVENT_DENIED);
877 }
878
reportAtlClosed(AGpsExtType agpsType)879 void AgpsManager::reportAtlClosed(AGpsExtType agpsType){
880
881 LOC_LOGD("AgpsManager::reportAtlClosed(): AgpsType %d", agpsType);
882
883 /* Fetch SM and send RELEASED event */
884 AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
885 sm->processAgpsEvent(AGPS_EVENT_RELEASED);
886 }
887
handleModemSSR()888 void AgpsManager::handleModemSSR(){
889
890 LOC_LOGD("AgpsManager::handleModemSSR");
891
892 /* Drop subscribers from all state machines */
893 if (mAgnssNif) {
894 mAgnssNif->dropAllSubscribers();
895 }
896 if (mInternetNif) {
897 mInternetNif->dropAllSubscribers();
898 }
899 if (mDsNif) {
900 mDsNif->dropAllSubscribers();
901 }
902
903 // reinitialize DS client in SSR mode
904 if (loc_core::ContextBase::mGps_conf.
905 USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
906
907 mDSClientStopDataCallFn();
908 mDSClientCloseDataCallFn();
909 mDSClientReleaseFn();
910
911 mDSClientInitFn(true);
912 }
913 }
914