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 * -------------------------------------------------------------------*/
40void 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
72void 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
116void 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
180void 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
203void 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
247void 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 */
293int 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
314void 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
349void 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
386void 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
396void 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
417void 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
436bool 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
448void 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
468AgpsSubscriber* 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
483AgpsSubscriber* 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
498void 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 * -------------------------------------------------------------------*/
514const int DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4;
515const int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500;
516
517/* Overridden method
518 * DS SM needs to handle one scenario differently */
519void 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 */
538void 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 */
554void 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 */
579int 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
648void 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 */
699void 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
735AgpsStateMachine* 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
766void 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
794void 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
828void AgpsManager::reportDataCallOpened(){
829
830    LOC_LOGD("AgpsManager::reportDataCallOpened");
831
832    if (mDsNif) {
833        mDsNif->processAgpsEvent(AGPS_EVENT_GRANTED);
834    }
835}
836
837void AgpsManager::reportDataCallClosed(){
838
839    LOC_LOGD("AgpsManager::reportDataCallClosed");
840
841    if (mDsNif) {
842        mDsNif->processAgpsEvent(AGPS_EVENT_RELEASED);
843    }
844}
845
846void 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
882void 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
891void 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
900void 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
927AGpsBearerType 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
945LocApnIpType 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