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     }
456 
457     if (apn == NULL || len <= 0) {
458         LOC_LOGD("Invalid apn len (%d) or null apn", len);
459         mAPN = NULL;
460         mAPNLen = 0;
461     }
462 
463     if (NULL != apn) {
464         mAPN = new char[len+1];
465         memcpy(mAPN, apn, len);
466         mAPN[len] = '\0';
467         mAPNLen = len;
468     }
469 }
470 
getSubscriber(int connHandle)471 AgpsSubscriber* AgpsStateMachine::getSubscriber(int connHandle){
472 
473     /* Go over the subscriber list */
474     std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
475     for (; it != mSubscriberList.end(); it++) {
476         AgpsSubscriber* subscriber = *it;
477         if (subscriber->mConnHandle == connHandle) {
478             return subscriber;
479         }
480     }
481 
482     /* Not found, return NULL */
483     return NULL;
484 }
485 
getFirstSubscriber(bool isInactive)486 AgpsSubscriber* AgpsStateMachine::getFirstSubscriber(bool isInactive){
487 
488     /* Go over the subscriber list */
489     std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
490     for (; it != mSubscriberList.end(); it++) {
491         AgpsSubscriber* subscriber = *it;
492         if(subscriber->mIsInactive == isInactive) {
493             return subscriber;
494         }
495     }
496 
497     /* Not found, return NULL */
498     return NULL;
499 }
500 
dropAllSubscribers()501 void AgpsStateMachine::dropAllSubscribers(){
502 
503     LOC_LOGD("dropAllSubscribers(): SM %p", this);
504 
505     /* Go over the subscriber list */
506     std::list<AgpsSubscriber*>::const_iterator it = mSubscriberList.begin();
507     while ( it != mSubscriberList.end() ) {
508         AgpsSubscriber* subscriber = *it;
509         it = mSubscriberList.erase(it);
510         delete subscriber;
511     }
512 }
513 
514 /* --------------------------------------------------------------------
515  *   DS State Machine Methods
516  * -------------------------------------------------------------------*/
517 const int DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4;
518 const int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500;
519 
520 /* Overridden method
521  * DS SM needs to handle one scenario differently */
processAgpsEvent(AgpsEvent event)522 void DSStateMachine::processAgpsEvent(AgpsEvent event) {
523 
524     LOC_LOGD("DSStateMachine::processAgpsEvent() %d", event);
525 
526     /* DS Client call setup APIs don't return failure/closure separately.
527      * Hence we receive RELEASED event in both cases.
528      * If we are in pending, we should consider RELEASED as DENIED */
529     if (event == AGPS_EVENT_RELEASED && mState == AGPS_STATE_PENDING) {
530 
531         LOC_LOGD("Translating RELEASED to DENIED event");
532         event = AGPS_EVENT_DENIED;
533     }
534 
535     /* Redirect process to base class */
536     AgpsStateMachine::processAgpsEvent(event);
537 }
538 
539 /* Timer Callback
540  * For the retry timer started in case of DS Client call setup failure */
delay_callback(void * callbackData,int result)541 void delay_callback(void *callbackData, int result)
542 {
543     LOC_LOGD("delay_callback(): cbData %p", callbackData);
544 
545     (void)result;
546 
547     if (callbackData == NULL) {
548         LOC_LOGE("delay_callback(): NULL argument received !");
549         return;
550     }
551     DSStateMachine* dsStateMachine = (DSStateMachine *)callbackData;
552     dsStateMachine->retryCallback();
553 }
554 
555 /* Invoked from Timer Callback
556  * For the retry timer started in case of DS Client call setup failure */
retryCallback()557 void DSStateMachine :: retryCallback()
558 {
559     LOC_LOGD("DSStateMachine::retryCallback()");
560 
561     /* Request SUPL ES
562      * There must be at least one active subscriber in list */
563     AgpsSubscriber* subscriber = getFirstSubscriber(false);
564     if (subscriber == NULL) {
565 
566         LOC_LOGE("No active subscriber for DS Client call setup");
567         return;
568     }
569 
570     /* Send message to retry */
571     mAgpsManager->mSendMsgToAdapterQueueFn(
572             new AgpsMsgRequestATL(
573                     mAgpsManager, subscriber->mConnHandle,
574                     LOC_AGPS_TYPE_SUPL_ES));
575 }
576 
577 /* Overridden method
578  * Request or Release data connection
579  * bool request :
580  *      true  = Request data connection
581  *      false = Release data connection */
requestOrReleaseDataConn(bool request)582 int DSStateMachine::requestOrReleaseDataConn(bool request){
583 
584     LOC_LOGD("DSStateMachine::requestOrReleaseDataConn(): "
585              "request %d", request);
586 
587     /* Release data connection required ? */
588     if (!request && mAgpsManager->mDSClientStopDataCallFn) {
589 
590         mAgpsManager->mDSClientStopDataCallFn();
591         LOC_LOGD("DS Client release data call request sent !");
592         return 0;
593     }
594 
595     /* Setup data connection request
596      * There must be at least one active subscriber in list */
597     AgpsSubscriber* subscriber = getFirstSubscriber(false);
598     if (subscriber == NULL) {
599 
600         LOC_LOGE("No active subscriber for DS Client call setup");
601         return -1;
602     }
603 
604     /* DS Client Fn registered ? */
605     if (!mAgpsManager->mDSClientOpenAndStartDataCallFn) {
606 
607         LOC_LOGE("DS Client start fn not registered, fallback to SUPL ATL");
608         notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false);
609         return -1;
610     }
611 
612     /* Setup the call */
613     int ret = mAgpsManager->mDSClientOpenAndStartDataCallFn();
614 
615     /* Check if data call start failed */
616     switch (ret) {
617 
618         case LOC_API_ADAPTER_ERR_ENGINE_BUSY:
619             LOC_LOGE("DS Client open call failed, err: %d", ret);
620             mRetries++;
621             if (mRetries > MAX_START_DATA_CALL_RETRIES) {
622 
623                 LOC_LOGE("DS Client call retries exhausted, "
624                          "falling back to normal SUPL ATL");
625                 notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false);
626             }
627             /* Retry DS Client call setup after some delay */
628             else if(loc_timer_start(
629                         DATA_CALL_RETRY_DELAY_MSEC, delay_callback, this)) {
630                     LOC_LOGE("Error: Could not start delay thread\n");
631                     return -1;
632                 }
633             break;
634 
635         case LOC_API_ADAPTER_ERR_UNSUPPORTED:
636             LOC_LOGE("No emergency profile found. Fall back to normal SUPL ATL");
637             notifyEventToSubscriber(AGPS_EVENT_DENIED, subscriber, false);
638             break;
639 
640         case LOC_API_ADAPTER_ERR_SUCCESS:
641             LOC_LOGD("Request to start data call sent");
642             break;
643 
644         default:
645             LOC_LOGE("Unrecognized return value: %d", ret);
646     }
647 
648     return ret;
649 }
650 
notifyEventToSubscriber(AgpsEvent event,AgpsSubscriber * subscriberToNotify,bool deleteSubscriberPostNotify)651 void DSStateMachine::notifyEventToSubscriber(
652         AgpsEvent event, AgpsSubscriber* subscriberToNotify,
653         bool deleteSubscriberPostNotify) {
654 
655     LOC_LOGD("DSStateMachine::notifyEventToSubscriber(): "
656              "SM %p, Event %d Subscriber %p Delete %d",
657              this, event, subscriberToNotify, deleteSubscriberPostNotify);
658 
659     switch (event) {
660 
661         case AGPS_EVENT_GRANTED:
662             mAgpsManager->mAtlOpenStatusCb(
663                     subscriberToNotify->mConnHandle, 1, NULL,
664                     AGPS_APN_BEARER_INVALID, LOC_AGPS_TYPE_SUPL_ES);
665             break;
666 
667         case AGPS_EVENT_DENIED:
668             /* Now try with regular SUPL
669              * We need to send request via message queue */
670             mRetries = 0;
671             mAgpsManager->mSendMsgToAdapterQueueFn(
672                     new AgpsMsgRequestATL(
673                             mAgpsManager, subscriberToNotify->mConnHandle,
674                             LOC_AGPS_TYPE_SUPL));
675             break;
676 
677         case AGPS_EVENT_UNSUBSCRIBE:
678             mAgpsManager->mAtlCloseStatusCb(subscriberToNotify->mConnHandle, 1);
679             break;
680 
681         case AGPS_EVENT_RELEASED:
682             mAgpsManager->mDSClientCloseDataCallFn();
683             mAgpsManager->mAtlCloseStatusCb(subscriberToNotify->mConnHandle, 1);
684             break;
685 
686         default:
687             LOC_LOGE("Invalid event %d", event);
688     }
689 
690     /* Search this subscriber in list and delete */
691     if (deleteSubscriberPostNotify) {
692         deleteSubscriber(subscriberToNotify);
693     }
694 }
695 
696 /* --------------------------------------------------------------------
697  *   Loc AGPS Manager Methods
698  * -------------------------------------------------------------------*/
699 
700 /* CREATE AGPS STATE MACHINES
701  * Must be invoked in Msg Handler context */
createAgpsStateMachines()702 void AgpsManager::createAgpsStateMachines() {
703 
704     LOC_LOGD("AgpsManager::createAgpsStateMachines");
705 
706     bool agpsCapable =
707             ((loc_core::ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA) ||
708                     (loc_core::ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB));
709 
710     if (NULL == mInternetNif) {
711         mInternetNif = new AgpsStateMachine(this, LOC_AGPS_TYPE_WWAN_ANY);
712         LOC_LOGD("Internet NIF: %p", mInternetNif);
713     }
714     if (agpsCapable) {
715         if (NULL == mAgnssNif) {
716             mAgnssNif = new AgpsStateMachine(this, LOC_AGPS_TYPE_SUPL);
717             LOC_LOGD("AGNSS NIF: %p", mAgnssNif);
718         }
719         if (NULL == mDsNif &&
720                 loc_core::ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
721 
722             if(!mDSClientInitFn){
723 
724                 LOC_LOGE("DS Client Init Fn not registered !");
725                 return;
726             }
727             if (mDSClientInitFn(false) != 0) {
728 
729                 LOC_LOGE("Failed to init data service client");
730                 return;
731             }
732             mDsNif = new DSStateMachine(this);
733             LOC_LOGD("DS NIF: %p", mDsNif);
734         }
735     }
736 }
737 
getAgpsStateMachine(AGpsExtType agpsType)738 AgpsStateMachine* AgpsManager::getAgpsStateMachine(AGpsExtType agpsType) {
739 
740     LOC_LOGD("AgpsManager::getAgpsStateMachine(): agpsType %d", agpsType);
741 
742     switch (agpsType) {
743 
744         case LOC_AGPS_TYPE_INVALID:
745         case LOC_AGPS_TYPE_SUPL:
746             if (mAgnssNif == NULL) {
747                 LOC_LOGE("NULL AGNSS NIF !");
748             }
749             return mAgnssNif;
750 
751         case LOC_AGPS_TYPE_SUPL_ES:
752             if (loc_core::ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
753                 if (mDsNif == NULL) {
754                     createAgpsStateMachines();
755                 }
756                 return mDsNif;
757             } else {
758                 return mAgnssNif;
759             }
760 
761         default:
762             return mInternetNif;
763     }
764 
765     LOC_LOGE("No SM found !");
766     return NULL;
767 }
768 
requestATL(int connHandle,AGpsExtType agpsType)769 void AgpsManager::requestATL(int connHandle, AGpsExtType agpsType){
770 
771     LOC_LOGD("AgpsManager::requestATL(): connHandle %d, agpsType %d",
772                connHandle, agpsType);
773 
774     AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
775 
776     if (sm == NULL) {
777 
778         LOC_LOGE("No AGPS State Machine for agpsType: %d", agpsType);
779         mAtlOpenStatusCb(
780                 connHandle, 0, NULL, AGPS_APN_BEARER_INVALID, agpsType);
781         return;
782     }
783 
784     /* Invoke AGPS SM processing */
785     AgpsSubscriber subscriber(connHandle, false, false);
786     sm->setCurrentSubscriber(&subscriber);
787 
788     /* If DS State Machine, wait for close complete */
789     if (agpsType == LOC_AGPS_TYPE_SUPL_ES) {
790         subscriber.mWaitForCloseComplete = true;
791     }
792 
793     /* Send subscriber event */
794     sm->processAgpsEvent(AGPS_EVENT_SUBSCRIBE);
795 }
796 
releaseATL(int connHandle)797 void AgpsManager::releaseATL(int connHandle){
798 
799     LOC_LOGD("AgpsManager::releaseATL(): connHandle %d", connHandle);
800 
801     /* First find the subscriber with specified handle.
802      * We need to search in all state machines. */
803     AgpsStateMachine* sm = NULL;
804     AgpsSubscriber* subscriber = NULL;
805 
806     if (mAgnssNif &&
807             (subscriber = mAgnssNif->getSubscriber(connHandle)) != NULL) {
808         sm = mAgnssNif;
809     }
810     else if (mInternetNif &&
811             (subscriber = mInternetNif->getSubscriber(connHandle)) != NULL) {
812         sm = mInternetNif;
813     }
814     else if (mDsNif &&
815             (subscriber = mDsNif->getSubscriber(connHandle)) != NULL) {
816         sm = mDsNif;
817     }
818 
819     if (sm == NULL) {
820         LOC_LOGE("Subscriber with connHandle %d not found in any SM",
821                     connHandle);
822         mAtlCloseStatusCb(connHandle, 0);
823         return;
824     }
825 
826     /* Now send unsubscribe event */
827     sm->setCurrentSubscriber(subscriber);
828     sm->processAgpsEvent(AGPS_EVENT_UNSUBSCRIBE);
829 }
830 
reportDataCallOpened()831 void AgpsManager::reportDataCallOpened(){
832 
833     LOC_LOGD("AgpsManager::reportDataCallOpened");
834 
835     if (mDsNif) {
836         mDsNif->processAgpsEvent(AGPS_EVENT_GRANTED);
837     }
838 }
839 
reportDataCallClosed()840 void AgpsManager::reportDataCallClosed(){
841 
842     LOC_LOGD("AgpsManager::reportDataCallClosed");
843 
844     if (mDsNif) {
845         mDsNif->processAgpsEvent(AGPS_EVENT_RELEASED);
846     }
847 }
848 
reportAtlOpenSuccess(AGpsExtType agpsType,char * apnName,int apnLen,LocApnIpType ipType)849 void AgpsManager::reportAtlOpenSuccess(
850         AGpsExtType agpsType, char* apnName, int apnLen,
851         LocApnIpType ipType){
852 
853     LOC_LOGD("AgpsManager::reportAtlOpenSuccess(): "
854              "AgpsType %d, APN [%s], Len %d, IPType %d",
855              agpsType, apnName, apnLen, ipType);
856 
857     /* Find the state machine instance */
858     AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
859 
860     /* Convert LocApnIpType sent by framework to AGpsBearerType */
861     AGpsBearerType bearerType;
862     switch (ipType) {
863         case LOC_APN_IP_IPV4:
864             bearerType = AGPS_APN_BEARER_IPV4;
865             break;
866         case LOC_APN_IP_IPV6:
867             bearerType = AGPS_APN_BEARER_IPV6;
868             break;
869         case LOC_APN_IP_IPV4V6:
870             bearerType = AGPS_APN_BEARER_IPV4V6;
871             break;
872         default:
873             bearerType = AGPS_APN_BEARER_IPV4;
874             break;
875     }
876 
877     /* Set bearer and apn info in state machine instance */
878     sm->setBearer(bearerType);
879     sm->setAPN(apnName, apnLen);
880 
881     /* Send GRANTED event to state machine */
882     sm->processAgpsEvent(AGPS_EVENT_GRANTED);
883 }
884 
reportAtlOpenFailed(AGpsExtType agpsType)885 void AgpsManager::reportAtlOpenFailed(AGpsExtType agpsType){
886 
887     LOC_LOGD("AgpsManager::reportAtlOpenFailed(): AgpsType %d", agpsType);
888 
889     /* Fetch SM and send DENIED event */
890     AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
891     sm->processAgpsEvent(AGPS_EVENT_DENIED);
892 }
893 
reportAtlClosed(AGpsExtType agpsType)894 void AgpsManager::reportAtlClosed(AGpsExtType agpsType){
895 
896     LOC_LOGD("AgpsManager::reportAtlClosed(): AgpsType %d", agpsType);
897 
898     /* Fetch SM and send RELEASED event */
899     AgpsStateMachine* sm = getAgpsStateMachine(agpsType);
900     sm->processAgpsEvent(AGPS_EVENT_RELEASED);
901 }
902 
handleModemSSR()903 void AgpsManager::handleModemSSR(){
904 
905     LOC_LOGD("AgpsManager::handleModemSSR");
906 
907     /* Drop subscribers from all state machines */
908     if (mAgnssNif) {
909         mAgnssNif->dropAllSubscribers();
910     }
911     if (mInternetNif) {
912         mInternetNif->dropAllSubscribers();
913     }
914     if (mDsNif) {
915         mDsNif->dropAllSubscribers();
916     }
917 
918     // reinitialize DS client in SSR mode
919     if (loc_core::ContextBase::mGps_conf.
920             USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) {
921 
922         mDSClientStopDataCallFn();
923         mDSClientCloseDataCallFn();
924         mDSClientReleaseFn();
925 
926         mDSClientInitFn(true);
927     }
928 }
929 
ipTypeToBearerType(LocApnIpType ipType)930 AGpsBearerType AgpsUtils::ipTypeToBearerType(LocApnIpType ipType) {
931 
932     switch (ipType) {
933 
934         case LOC_APN_IP_IPV4:
935             return AGPS_APN_BEARER_IPV4;
936 
937         case LOC_APN_IP_IPV6:
938             return AGPS_APN_BEARER_IPV6;
939 
940         case LOC_APN_IP_IPV4V6:
941             return AGPS_APN_BEARER_IPV4V6;
942 
943         default:
944             return AGPS_APN_BEARER_IPV4;
945     }
946 }
947 
bearerTypeToIpType(AGpsBearerType bearerType)948 LocApnIpType AgpsUtils::bearerTypeToIpType(AGpsBearerType bearerType){
949 
950     switch (bearerType) {
951 
952         case AGPS_APN_BEARER_IPV4:
953             return LOC_APN_IP_IPV4;
954 
955         case AGPS_APN_BEARER_IPV6:
956             return LOC_APN_IP_IPV6;
957 
958         case AGPS_APN_BEARER_IPV4V6:
959             return LOC_APN_IP_IPV4V6;
960 
961         default:
962             return LOC_APN_IP_IPV4;
963     }
964 }
965