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