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