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