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