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