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 notifyEventToSubscriber(
133 AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, false);
134 }
135 else{
136 /* Notify only current subscriber and then delete it from
137 * subscriberList */
138 notifyEventToSubscriber(
139 AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, true);
140 }
141
142 /* If no subscribers in list, release data connection */
143 if(mSubscriberList.empty()){
144 transitionState(AGPS_STATE_RELEASED);
145 requestOrReleaseDataConn(false);
146 }
147 /* Some subscribers in list, but all inactive;
148 * Release data connection */
149 else if(!anyActiveSubscribers()){
150 transitionState(AGPS_STATE_RELEASING);
151 requestOrReleaseDataConn(false);
152 }
153 break;
154
155 case AGPS_STATE_RELEASING:
156 /* If the subscriber wishes to wait for connection close,
157 * before being removed from list, move to inactive state
158 * and notify */
159 if(mCurrentSubscriber->mWaitForCloseComplete){
160 mCurrentSubscriber->mIsInactive = true;
161 notifyEventToSubscriber(
162 AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, false);
163 }
164 else{
165 /* Notify only current subscriber and then delete it from
166 * subscriberList */
167 notifyEventToSubscriber(
168 AGPS_EVENT_UNSUBSCRIBE, mCurrentSubscriber, true);
169 }
170
171 /* If no subscribers in list, just move the state.
172 * Request for releasing data connection should already have been
173 * sent */
174 if(mSubscriberList.empty()){
175 transitionState(AGPS_STATE_RELEASED);
176 }
177 break;
178
179 default:
180 LOC_LOGE("Invalid state: %d", mState);
181 }
182 }
183
processAgpsEventGranted()184 void AgpsStateMachine::processAgpsEventGranted(){
185
186 switch (mState){
187
188 case AGPS_STATE_RELEASED:
189 case AGPS_STATE_ACQUIRED:
190 case AGPS_STATE_RELEASING:
191 LOC_LOGE("Unexpected event GRANTED in state %d", mState);
192 break;
193
194 case AGPS_STATE_PENDING:
195 // Move to acquired state
196 transitionState(AGPS_STATE_ACQUIRED);
197 notifyAllSubscribers(
198 AGPS_EVENT_GRANTED, false,
199 AGPS_NOTIFICATION_TYPE_FOR_ACTIVE_SUBSCRIBERS);
200 break;
201
202 default:
203 LOC_LOGE("Invalid state: %d", mState);
204 }
205 }
206
processAgpsEventReleased()207 void AgpsStateMachine::processAgpsEventReleased(){
208
209 switch (mState){
210
211 case AGPS_STATE_RELEASED:
212 LOC_LOGE("Unexpected event RELEASED in state %d", mState);
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 AgpsFrameworkInterface::AGnssStatusIpV4 nifRequest;
300 memset(&nifRequest, 0, sizeof(nifRequest));
301
302 nifRequest.type = (AgpsFrameworkInterface::AGnssType)mAgpsType;
303
304 if(request){
305 LOC_LOGD("AGPS Data Conn Request");
306 nifRequest.status = (AgpsFrameworkInterface::AGnssStatusValue)
307 LOC_GPS_REQUEST_AGPS_DATA_CONN;
308 }
309 else{
310 LOC_LOGD("AGPS Data Conn Release");
311 nifRequest.status = (AgpsFrameworkInterface::AGnssStatusValue)
312 LOC_GPS_RELEASE_AGPS_DATA_CONN;
313 }
314
315 mAgpsManager->mFrameworkStatusV4Cb(nifRequest);
316 return 0;
317 }
318
notifyAllSubscribers(AgpsEvent event,bool deleteSubscriberPostNotify,AgpsNotificationType notificationType)319 void AgpsStateMachine::notifyAllSubscribers(
320 AgpsEvent event, bool deleteSubscriberPostNotify,
321 AgpsNotificationType notificationType){
322
323 LOC_LOGD("notifyAllSubscribers(): "
324 "SM %p, Event %d Delete %d Notification Type %d",
325 this, event, deleteSubscriberPostNotify, notificationType);
326
327 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
328 while ( it != mSubscriberList.end() ){
329
330 AgpsSubscriber* subscriber = *it;
331
332 if(notificationType == AGPS_NOTIFICATION_TYPE_FOR_ALL_SUBSCRIBERS ||
333 (notificationType == AGPS_NOTIFICATION_TYPE_FOR_INACTIVE_SUBSCRIBERS &&
334 subscriber->mIsInactive) ||
335 (notificationType == AGPS_NOTIFICATION_TYPE_FOR_ACTIVE_SUBSCRIBERS &&
336 !subscriber->mIsInactive)) {
337
338 /* Deleting via this call would require another traversal
339 * through subscriber list, inefficient; hence pass in false*/
340 notifyEventToSubscriber(event, subscriber, false);
341
342 if(deleteSubscriberPostNotify){
343 it = mSubscriberList.erase(it);
344 delete subscriber;
345 } else{
346 it++;
347 }
348 } else{
349 it++;
350 }
351 }
352 }
353
notifyEventToSubscriber(AgpsEvent event,AgpsSubscriber * subscriberToNotify,bool deleteSubscriberPostNotify)354 void AgpsStateMachine::notifyEventToSubscriber(
355 AgpsEvent event, AgpsSubscriber* subscriberToNotify,
356 bool deleteSubscriberPostNotify) {
357
358 LOC_LOGD("notifyEventToSubscriber(): "
359 "SM %p, Event %d Subscriber %p Delete %d",
360 this, event, subscriberToNotify, deleteSubscriberPostNotify);
361
362 switch (event){
363
364 case AGPS_EVENT_GRANTED:
365 mAgpsManager->mAtlOpenStatusCb(
366 subscriberToNotify->mConnHandle, 1, getAPN(),
367 getBearer(), mAgpsType);
368 break;
369
370 case AGPS_EVENT_DENIED:
371 mAgpsManager->mAtlOpenStatusCb(
372 subscriberToNotify->mConnHandle, 0, getAPN(),
373 getBearer(), mAgpsType);
374 break;
375
376 case AGPS_EVENT_UNSUBSCRIBE:
377 case AGPS_EVENT_RELEASED:
378 mAgpsManager->mAtlCloseStatusCb(subscriberToNotify->mConnHandle, 1);
379 break;
380
381 default:
382 LOC_LOGE("Invalid event %d", event);
383 }
384
385 /* Search this subscriber in list and delete */
386 if (deleteSubscriberPostNotify) {
387 deleteSubscriber(subscriberToNotify);
388 }
389 }
390
transitionState(AgpsState newState)391 void AgpsStateMachine::transitionState(AgpsState newState){
392
393 LOC_LOGD("transitionState(): SM %p, old %d, new %d",
394 this, mState, newState);
395
396 mState = newState;
397
398 // notify state transitions to all subscribers ?
399 }
400
addSubscriber(AgpsSubscriber * subscriberToAdd)401 void AgpsStateMachine::addSubscriber(AgpsSubscriber* subscriberToAdd){
402
403 LOC_LOGD("addSubscriber(): SM %p, Subscriber %p",
404 this, subscriberToAdd);
405
406 // Check if subscriber is already present in the current list
407 // If not, then add
408 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
409 for(; it != mSubscriberList.end(); it++){
410 AgpsSubscriber* subscriber = *it;
411 if(subscriber->equals(subscriberToAdd)){
412 LOC_LOGE("Subscriber already in list");
413 return;
414 }
415 }
416
417 AgpsSubscriber* cloned = subscriberToAdd->clone();
418 LOC_LOGD("addSubscriber(): cloned subscriber: %p", cloned);
419 mSubscriberList.push_back(cloned);
420 }
421
deleteSubscriber(AgpsSubscriber * subscriberToDelete)422 void AgpsStateMachine::deleteSubscriber(AgpsSubscriber* subscriberToDelete){
423
424 LOC_LOGD("deleteSubscriber(): SM %p, Subscriber %p",
425 this, subscriberToDelete);
426
427 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
428 while ( it != mSubscriberList.end() ) {
429
430 AgpsSubscriber* subscriber = *it;
431 if(subscriber && subscriber->equals(subscriberToDelete)){
432
433 it = mSubscriberList.erase(it);
434 delete subscriber;
435 }else{
436 it++;
437 }
438 }
439 }
440
anyActiveSubscribers()441 bool AgpsStateMachine::anyActiveSubscribers(){
442
443 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
444 for(; it != mSubscriberList.end(); it++){
445 AgpsSubscriber* subscriber = *it;
446 if(!subscriber->mIsInactive){
447 return true;
448 }
449 }
450 return false;
451 }
452
setAPN(char * apn,unsigned int len)453 void AgpsStateMachine::setAPN(char* apn, unsigned int len){
454
455 if (NULL != mAPN) {
456 delete mAPN;
457 }
458
459 if(apn == NULL || len <= 0){
460 LOC_LOGD("Invalid apn len (%d) or null apn", len);
461 mAPN = NULL;
462 mAPNLen = 0;
463 }
464
465 if (NULL != apn) {
466 mAPN = new char[len+1];
467 memcpy(mAPN, apn, len);
468 mAPN[len] = '\0';
469 mAPNLen = len;
470 }
471 }
472
getSubscriber(int connHandle)473 AgpsSubscriber* AgpsStateMachine::getSubscriber(int connHandle){
474
475 /* Go over the subscriber list */
476 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
477 for(; it != mSubscriberList.end(); it++){
478 AgpsSubscriber* subscriber = *it;
479 if(subscriber->mConnHandle == connHandle){
480 return subscriber;
481 }
482 }
483
484 /* Not found, return NULL */
485 return NULL;
486 }
487
getFirstSubscriber(bool isInactive)488 AgpsSubscriber* AgpsStateMachine::getFirstSubscriber(bool isInactive){
489
490 /* Go over the subscriber list */
491 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
492 for(; it != mSubscriberList.end(); it++){
493 AgpsSubscriber* subscriber = *it;
494 if(subscriber->mIsInactive == isInactive){
495 return subscriber;
496 }
497 }
498
499 /* Not found, return NULL */
500 return NULL;
501 }
502
dropAllSubscribers()503 void AgpsStateMachine::dropAllSubscribers(){
504
505 LOC_LOGD("dropAllSubscribers(): SM %p", this);
506
507 /* Go over the subscriber list */
508 std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
509 while ( it != mSubscriberList.end() ){
510 AgpsSubscriber* subscriber = *it;
511 it = mSubscriberList.erase(it);
512 delete subscriber;
513 }
514 }
515
516 /* --------------------------------------------------------------------
517 * DS State Machine Methods
518 * -------------------------------------------------------------------*/
519 const int DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4;
520 const int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500;
521
522 /* Overridden method
523 * DS SM needs to handle one scenario differently */
processAgpsEvent(AgpsEvent event)524 void DSStateMachine::processAgpsEvent(AgpsEvent event){
525
526 LOC_LOGD("DSStateMachine::processAgpsEvent() %d", event);
527
528 /* DS Client call setup APIs don't return failure/closure separately.
529 * Hence we receive RELEASED event in both cases.
530 * If we are in pending, we should consider RELEASED as DENIED */
531 if(event == AGPS_EVENT_RELEASED && mState == AGPS_STATE_PENDING){
532
533 LOC_LOGD("Translating RELEASED to DENIED event");
534 event = AGPS_EVENT_DENIED;
535 }
536
537 /* Redirect process to base class */
538 AgpsStateMachine::processAgpsEvent(event);
539 }
540
541 /* Timer Callback
542 * For the retry timer started in case of DS Client call setup failure */
delay_callback(void * callbackData,int result)543 void delay_callback(void *callbackData, int result)
544 {
545 LOC_LOGD("delay_callback(): cbData %p", callbackData);
546
547 (void)result;
548
549 if(callbackData == NULL) {
550 LOC_LOGE("delay_callback(): NULL argument received !");
551 return;
552 }
553 DSStateMachine* dsStateMachine = (DSStateMachine *)callbackData;
554 dsStateMachine->retryCallback();
555 }
556
557 /* Invoked from Timer Callback
558 * For the retry timer started in case of DS Client call setup failure */
retryCallback()559 void DSStateMachine :: retryCallback()
560 {
561 LOC_LOGD("DSStateMachine::retryCallback()");
562
563 /* Request SUPL ES
564 * There must be at least one active subscriber in list */
565 AgpsSubscriber* subscriber = getFirstSubscriber(false);
566 if(subscriber == NULL) {
567
568 LOC_LOGE("No active subscriber for DS Client call setup");
569 return;
570 }
571
572 /* Send message to retry */
573 mAgpsManager->mSendMsgToAdapterQueueFn(
574 new AgpsMsgRequestATL(
575 mAgpsManager, subscriber->mConnHandle,
576 LOC_AGPS_TYPE_SUPL_ES));
577 }
578
579 /* Overridden method
580 * Request or Release data connection
581 * bool request :
582 * true = Request data connection
583 * false = Release data connection */
requestOrReleaseDataConn(bool request)584 int DSStateMachine::requestOrReleaseDataConn(bool request){
585
586 LOC_LOGD("DSStateMachine::requestOrReleaseDataConn(): "
587 "request %d", request);
588
589 /* Release data connection required ? */
590 if(!request && mAgpsManager->mDSClientStopDataCallFn){
591
592 mAgpsManager->mDSClientStopDataCallFn();
593 LOC_LOGD("DS Client release data call request sent !");
594 return 0;
595 }
596
597 /* Setup data connection request
598 * There must be at least one active subscriber in list */
599 AgpsSubscriber* subscriber = getFirstSubscriber(false);
600 if(subscriber == NULL) {
601
602 LOC_LOGE("No active subscriber for DS Client call setup");
603 return -1;
604 }
605
606 /* DS Client Fn registered ? */
607 if(!mAgpsManager->mDSClientOpenAndStartDataCallFn){
608
609 LOC_LOGE("DS Client start fn not registered, fallback to SUPL ATL");
610 notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false);
611 return -1;
612 }
613
614 /* Setup the call */
615 int ret = mAgpsManager->mDSClientOpenAndStartDataCallFn();
616
617 /* Check if data call start failed */
618 switch (ret) {
619
620 case LOC_API_ADAPTER_ERR_ENGINE_BUSY:
621 LOC_LOGE("DS Client open call failed, err: %d", ret);
622 mRetries++;
623 if(mRetries > MAX_START_DATA_CALL_RETRIES) {
624
625 LOC_LOGE("DS Client call retries exhausted, "
626 "falling back to normal SUPL ATL");
627 notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false);
628 }
629 /* Retry DS Client call setup after some delay */
630 else if(loc_timer_start(
631 DATA_CALL_RETRY_DELAY_MSEC, delay_callback, this)) {
632 LOC_LOGE("Error: Could not start delay thread\n");
633 return -1;
634 }
635 break;
636
637 case LOC_API_ADAPTER_ERR_UNSUPPORTED:
638 LOC_LOGE("No emergency profile found. Fall back to normal SUPL ATL");
639 notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false);
640 break;
641
642 case LOC_API_ADAPTER_ERR_SUCCESS:
643 LOC_LOGD("Request to start data call sent");
644 break;
645
646 default:
647 LOC_LOGE("Unrecognized return value: %d", ret);
648 }
649
650 return ret;
651 }
652
notifyEventToSubscriber(AgpsEvent event,AgpsSubscriber * subscriberToNotify,bool deleteSubscriberPostNotify)653 void DSStateMachine::notifyEventToSubscriber(
654 AgpsEvent event, AgpsSubscriber* subscriberToNotify,
655 bool deleteSubscriberPostNotify) {
656
657 LOC_LOGD("DSStateMachine::notifyEventToSubscriber(): "
658 "SM %p, Event %d Subscriber %p Delete %d",
659 this, event, subscriberToNotify, deleteSubscriberPostNotify);
660
661 switch (event){
662
663 case AGPS_EVENT_GRANTED:
664 mAgpsManager->mAtlOpenStatusCb(
665 subscriberToNotify->mConnHandle, 1, NULL,
666 AGPS_APN_BEARER_INVALID, LOC_AGPS_TYPE_SUPL_ES);
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));
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)771 void AgpsManager::requestATL(int connHandle, AGpsExtType agpsType){
772
773 LOC_LOGD("AgpsManager::requestATL(): connHandle %d, agpsType %d",
774 connHandle, agpsType);
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);
783 return;
784 }
785
786 /* Invoke AGPS SM processing */
787 AgpsSubscriber subscriber(connHandle, false, false);
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,LocApnIpType ipType)851 void AgpsManager::reportAtlOpenSuccess(
852 AGpsExtType agpsType, char* apnName, int apnLen,
853 LocApnIpType ipType){
854
855 LOC_LOGD("AgpsManager::reportAtlOpenSuccess(): "
856 "AgpsType %d, APN [%s], Len %d, IPType %d",
857 agpsType, apnName, apnLen, ipType);
858
859 /* Find the state machine instance */
860 AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
861
862 /* Convert LocApnIpType sent by framework to AGpsBearerType */
863 AGpsBearerType bearerType;
864 switch (ipType) {
865 case LOC_APN_IP_IPV4:
866 bearerType = AGPS_APN_BEARER_IPV4;
867 break;
868 case LOC_APN_IP_IPV6:
869 bearerType = AGPS_APN_BEARER_IPV6;
870 break;
871 case LOC_APN_IP_IPV4V6:
872 bearerType = AGPS_APN_BEARER_IPV4V6;
873 break;
874 default:
875 bearerType = AGPS_APN_BEARER_IPV4;
876 break;
877 }
878
879 /* Set bearer and apn info in state machine instance */
880 sm->setBearer(bearerType);
881 sm->setAPN(apnName, apnLen);
882
883 /* Send GRANTED event to state machine */
884 sm->processAgpsEvent(AGPS_EVENT_GRANTED);
885 }
886
reportAtlOpenFailed(AGpsExtType agpsType)887 void AgpsManager::reportAtlOpenFailed(AGpsExtType agpsType){
888
889 LOC_LOGD("AgpsManager::reportAtlOpenFailed(): AgpsType %d", agpsType);
890
891 /* Fetch SM and send DENIED event */
892 AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
893 sm->processAgpsEvent(AGPS_EVENT_DENIED);
894 }
895
reportAtlClosed(AGpsExtType agpsType)896 void AgpsManager::reportAtlClosed(AGpsExtType agpsType){
897
898 LOC_LOGD("AgpsManager::reportAtlClosed(): AgpsType %d", agpsType);
899
900 /* Fetch SM and send RELEASED event */
901 AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
902 sm->processAgpsEvent(AGPS_EVENT_RELEASED);
903 }
904
handleModemSSR()905 void AgpsManager::handleModemSSR(){
906
907 LOC_LOGD("AgpsManager::handleModemSSR");
908
909 /* Drop subscribers from all state machines */
910 if (mAgnssNif){
911 mAgnssNif->dropAllSubscribers();
912 }
913 if (mInternetNif){
914 mInternetNif->dropAllSubscribers();
915 }
916 if(mDsNif){
917 mDsNif->dropAllSubscribers();
918 }
919
920 // reinitialize DS client in SSR mode
921 if(loc_core::ContextBase::mGps_conf.
922 USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL){
923
924 mDSClientStopDataCallFn();
925 mDSClientCloseDataCallFn();
926 mDSClientReleaseFn();
927
928 mDSClientInitFn(true);
929 }
930 }
931
ipTypeToBearerType(LocApnIpType ipType)932 AGpsBearerType AgpsUtils::ipTypeToBearerType(LocApnIpType ipType) {
933
934 switch (ipType) {
935
936 case LOC_APN_IP_IPV4:
937 return AGPS_APN_BEARER_IPV4;
938
939 case LOC_APN_IP_IPV6:
940 return AGPS_APN_BEARER_IPV6;
941
942 case LOC_APN_IP_IPV4V6:
943 return AGPS_APN_BEARER_IPV4V6;
944
945 default:
946 return AGPS_APN_BEARER_IPV4;
947 }
948 }
949
bearerTypeToIpType(AGpsBearerType bearerType)950 LocApnIpType AgpsUtils::bearerTypeToIpType(AGpsBearerType bearerType){
951
952 switch (bearerType) {
953
954 case AGPS_APN_BEARER_IPV4:
955 return LOC_APN_IP_IPV4;
956
957 case AGPS_APN_BEARER_IPV6:
958 return LOC_APN_IP_IPV6;
959
960 case AGPS_APN_BEARER_IPV4V6:
961 return LOC_APN_IP_IPV4V6;
962
963 default:
964 return LOC_APN_IP_IPV4;
965 }
966 }
967