Home | History | Annotate | Download | only in libloc_api_50001
      1 /* Copyright (c) 2011-2013, 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_NDDEBUG 0
     31 #define LOG_TAG "LocSvc_eng"
     32 
     33 #include <loc_eng_agps.h>
     34 #include <loc_eng_log.h>
     35 #include <log_util.h>
     36 #include <platform_lib_includes.h>
     37 #include <loc_eng_dmn_conn_handler.h>
     38 #include <loc_eng_dmn_conn.h>
     39 #include <sys/time.h>
     40 
     41 //======================================================================
     42 // C callbacks
     43 //======================================================================
     44 
     45 // This is given to linked_list_add as the dealloc callback
     46 // data -- an instance of Subscriber
     47 static void deleteObj(void* data)
     48 {
     49     delete (Subscriber*)data;
     50 }
     51 
     52 // This is given to linked_list_search() as the comparison callback
     53 // when the state manchine needs to process for particular subscriber
     54 // fromCaller -- caller provides this obj
     55 // fromList -- linked_list_search() function take this one from list
     56 static bool hasSubscriber(void* fromCaller, void* fromList)
     57 {
     58     Notification* notification = (Notification*)fromCaller;
     59     Subscriber* s1 = (Subscriber*)fromList;
     60 
     61     return s1->forMe(*notification);
     62 }
     63 
     64 // This is gvien to linked_list_search() to notify subscriber objs
     65 // when the state machine needs to inform all subscribers of resource
     66 // status changes, e.g. when resource is GRANTED.
     67 // fromCaller -- caller provides this ptr to a Notification obj.
     68 // fromList -- linked_list_search() function take this one from list
     69 static bool notifySubscriber(void* fromCaller, void* fromList)
     70 {
     71     Notification* notification = (Notification*)fromCaller;
     72     Subscriber* s1 = (Subscriber*)fromList;
     73 
     74     // we notify every subscriber indiscriminatively
     75     // each subscriber decides if this notification is interesting.
     76     return s1->notifyRsrcStatus(*notification) &&
     77            // if we do not want to delete the subscriber from the
     78            // the list, we must set this to false so this function
     79            // returns false
     80            notification->postNotifyDelete;
     81 }
     82 
     83 //======================================================================
     84 // Notification
     85 //======================================================================
     86 const int Notification::BROADCAST_ALL = 0x80000000;
     87 const int Notification::BROADCAST_ACTIVE = 0x80000001;
     88 const int Notification::BROADCAST_INACTIVE = 0x80000002;
     89 const unsigned char DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4;
     90 const unsigned int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500;
     91 //======================================================================
     92 // Subscriber:  BITSubscriber / ATLSubscriber / WIFISubscriber
     93 //======================================================================
     94 bool Subscriber::forMe(Notification &notification)
     95 {
     96     if (NULL != notification.rcver) {
     97         return equals(notification.rcver);
     98     } else {
     99         return Notification::BROADCAST_ALL == notification.groupID ||
    100             (Notification::BROADCAST_ACTIVE == notification.groupID &&
    101              !isInactive()) ||
    102             (Notification::BROADCAST_INACTIVE == notification.groupID &&
    103              isInactive());
    104     }
    105 }
    106 bool BITSubscriber::equals(const Subscriber *s) const
    107 {
    108     BITSubscriber* bitS = (BITSubscriber*)s;
    109 
    110     return (ID == bitS->ID &&
    111             (INADDR_NONE != (unsigned int)ID ||
    112              0 == strncmp(mIPv6Addr, bitS->mIPv6Addr, sizeof(mIPv6Addr))));
    113 }
    114 
    115 bool BITSubscriber::notifyRsrcStatus(Notification &notification)
    116 {
    117     bool notify = forMe(notification);
    118 
    119     if (notify) {
    120         switch(notification.rsrcStatus)
    121         {
    122         case RSRC_UNSUBSCRIBE:
    123         case RSRC_RELEASED:
    124             loc_eng_dmn_conn_loc_api_server_data_conn(
    125                 LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON,
    126                 GPSONE_LOC_API_IF_RELEASE_SUCCESS);
    127             break;
    128         case RSRC_DENIED:
    129             loc_eng_dmn_conn_loc_api_server_data_conn(
    130                 LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON,
    131                 GPSONE_LOC_API_IF_FAILURE);
    132             break;
    133         case RSRC_GRANTED:
    134             loc_eng_dmn_conn_loc_api_server_data_conn(
    135                 LOC_ENG_IF_REQUEST_SENDER_ID_GPSONE_DAEMON,
    136                 GPSONE_LOC_API_IF_REQUEST_SUCCESS);
    137             break;
    138         default:
    139             notify = false;
    140         }
    141     }
    142 
    143     return notify;
    144 }
    145 
    146 bool ATLSubscriber::notifyRsrcStatus(Notification &notification)
    147 {
    148     bool notify = forMe(notification);
    149 
    150     if (notify) {
    151         switch(notification.rsrcStatus)
    152         {
    153         case RSRC_UNSUBSCRIBE:
    154         case RSRC_RELEASED:
    155             ((LocEngAdapter*)mLocAdapter)->atlCloseStatus(ID, 1);
    156             break;
    157         case RSRC_DENIED:
    158         {
    159             AGpsExtType type = mBackwardCompatibleMode ?
    160                               AGPS_TYPE_INVALID : mStateMachine->getType();
    161             ((LocEngAdapter*)mLocAdapter)->atlOpenStatus(ID, 0,
    162                                             (char*)mStateMachine->getAPN(),
    163                                             mStateMachine->getBearer(),
    164                                             type);
    165         }
    166             break;
    167         case RSRC_GRANTED:
    168         {
    169             AGpsExtType type = mBackwardCompatibleMode ?
    170                               AGPS_TYPE_INVALID : mStateMachine->getType();
    171             ((LocEngAdapter*)mLocAdapter)->atlOpenStatus(ID, 1,
    172                                             (char*)mStateMachine->getAPN(),
    173                                             mStateMachine->getBearer(),
    174                                             type);
    175         }
    176             break;
    177         default:
    178             notify = false;
    179         }
    180     }
    181 
    182     return notify;
    183 }
    184 
    185 bool WIFISubscriber::notifyRsrcStatus(Notification &notification)
    186 {
    187     bool notify = forMe(notification);
    188 
    189     if (notify) {
    190         switch(notification.rsrcStatus)
    191         {
    192         case RSRC_UNSUBSCRIBE:
    193             break;
    194         case RSRC_RELEASED:
    195             loc_eng_dmn_conn_loc_api_server_data_conn(
    196                 senderId,
    197                 GPSONE_LOC_API_IF_RELEASE_SUCCESS);
    198             break;
    199         case RSRC_DENIED:
    200             loc_eng_dmn_conn_loc_api_server_data_conn(
    201                 senderId,
    202                 GPSONE_LOC_API_IF_FAILURE);
    203             break;
    204         case RSRC_GRANTED:
    205             loc_eng_dmn_conn_loc_api_server_data_conn(
    206                 senderId,
    207                 GPSONE_LOC_API_IF_REQUEST_SUCCESS);
    208             break;
    209         default:
    210             notify = false;
    211         }
    212     }
    213 
    214     return notify;
    215 }
    216 bool DSSubscriber::notifyRsrcStatus(Notification &notification)
    217 {
    218     bool notify = forMe(notification);
    219     LOC_LOGD("DSSubscriber::notifyRsrcStatus. notify:%d \n",(int)(notify));
    220     if(notify) {
    221         switch(notification.rsrcStatus) {
    222         case RSRC_UNSUBSCRIBE:
    223         case RSRC_RELEASED:
    224         case RSRC_DENIED:
    225         case RSRC_GRANTED:
    226             ((DSStateMachine *)mStateMachine)->informStatus(notification.rsrcStatus, ID);
    227             break;
    228         default:
    229             notify = false;
    230         }
    231     }
    232     return notify;
    233 }
    234 void DSSubscriber :: setInactive()
    235 {
    236     mIsInactive = true;
    237     ((DSStateMachine *)mStateMachine)->informStatus(RSRC_UNSUBSCRIBE, ID);
    238 }
    239 //======================================================================
    240 // AgpsState:  AgpsReleasedState / AgpsPendingState / AgpsAcquiredState
    241 //======================================================================
    242 
    243 // AgpsReleasedState
    244 class AgpsReleasedState : public AgpsState
    245 {
    246     friend class AgpsStateMachine;
    247 
    248     inline AgpsReleasedState(AgpsStateMachine* stateMachine) :
    249         AgpsState(stateMachine)
    250     { mReleasedState = this; }
    251 
    252     inline ~AgpsReleasedState() {}
    253 public:
    254     virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
    255     inline virtual char* whoami() {return (char*)"AgpsReleasedState";}
    256 };
    257 
    258 AgpsState* AgpsReleasedState::onRsrcEvent(AgpsRsrcStatus event, void* data)
    259 {
    260     LOC_LOGD("AgpsReleasedState::onRsrcEvent; event:%d\n", (int)event);
    261     if (mStateMachine->hasSubscribers()) {
    262         LOC_LOGE("Error: %s subscriber list not empty!!!", whoami());
    263         // I don't know how to recover from it.  I am adding this rather
    264         // for debugging purpose.
    265     }
    266 
    267     AgpsState* nextState = this;
    268     switch (event)
    269     {
    270     case RSRC_SUBSCRIBE:
    271     {
    272         // no notification until we get RSRC_GRANTED
    273         // but we need to add subscriber to the list
    274         mStateMachine->addSubscriber((Subscriber*)data);
    275         // request from connecivity service for NIF
    276         //The if condition is added so that if the data call setup fails
    277         //for DS State Machine, we want to retry in released state.
    278         //for AGps State Machine, sendRsrcRequest() will always return success
    279         if(!mStateMachine->sendRsrcRequest(GPS_REQUEST_AGPS_DATA_CONN)) {
    280             // move the state to PENDING
    281             nextState = mPendingState;
    282         }
    283     }
    284     break;
    285 
    286     case RSRC_UNSUBSCRIBE:
    287     {
    288         // the list should really be empty, nothing to remove.
    289         // but we might as well just tell the client it is
    290         // unsubscribed.  False tolerance, right?
    291         Subscriber* subscriber = (Subscriber*) data;
    292         Notification notification(subscriber, event, false);
    293         subscriber->notifyRsrcStatus(notification);
    294     }
    295         // break;
    296     case RSRC_GRANTED:
    297     case RSRC_RELEASED:
    298     case RSRC_DENIED:
    299     default:
    300         LOC_LOGW("%s: unrecognized event %d", whoami(), event);
    301         // no state change.
    302         break;
    303     }
    304 
    305     LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d",
    306              whoami(), nextState->whoami(), event);
    307     return nextState;
    308 }
    309 
    310 // AgpsPendingState
    311 class AgpsPendingState : public AgpsState
    312 {
    313     friend class AgpsStateMachine;
    314 
    315     inline AgpsPendingState(AgpsStateMachine* stateMachine) :
    316         AgpsState(stateMachine)
    317     { mPendingState = this; }
    318 
    319     inline ~AgpsPendingState() {}
    320 public:
    321     virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
    322     inline virtual char* whoami() {return (char*)"AgpsPendingState";}
    323 };
    324 
    325 AgpsState* AgpsPendingState::onRsrcEvent(AgpsRsrcStatus event, void* data)
    326 {
    327     AgpsState* nextState = this;;
    328     LOC_LOGD("AgpsPendingState::onRsrcEvent; event:%d\n", (int)event);
    329     switch (event)
    330     {
    331     case RSRC_SUBSCRIBE:
    332     {
    333         // already requested for NIF resource,
    334         // do nothing until we get RSRC_GRANTED indication
    335         // but we need to add subscriber to the list
    336         mStateMachine->addSubscriber((Subscriber*)data);
    337         // no state change.
    338     }
    339         break;
    340 
    341     case RSRC_UNSUBSCRIBE:
    342     {
    343         Subscriber* subscriber = (Subscriber*) data;
    344         if (subscriber->waitForCloseComplete()) {
    345             subscriber->setInactive();
    346         } else {
    347             // auto notify this subscriber of the unsubscribe
    348             Notification notification(subscriber, event, true);
    349             mStateMachine->notifySubscribers(notification);
    350         }
    351 
    352         // now check if there is any subscribers left
    353         if (!mStateMachine->hasSubscribers()) {
    354             // no more subscribers, move to RELEASED state
    355             nextState = mReleasedState;
    356 
    357             // tell connecivity service we can release NIF
    358             mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
    359         } else if (!mStateMachine->hasActiveSubscribers()) {
    360             // only inactive subscribers, move to RELEASING state
    361             nextState = mReleasingState;
    362 
    363             // tell connecivity service we can release NIF
    364             mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
    365         }
    366     }
    367     break;
    368 
    369     case RSRC_GRANTED:
    370     {
    371         nextState = mAcquiredState;
    372         Notification notification(Notification::BROADCAST_ACTIVE, event, false);
    373         // notify all subscribers NIF resource GRANTED
    374         // by setting false, we keep subscribers on the linked list
    375         mStateMachine->notifySubscribers(notification);
    376     }
    377         break;
    378 
    379     case RSRC_RELEASED:
    380         // no state change.
    381         // we are expecting either GRANTED or DENIED.  Handling RELEASED
    382         // may like break our state machine in race conditions.
    383         break;
    384 
    385     case RSRC_DENIED:
    386     {
    387         nextState = mReleasedState;
    388         Notification notification(Notification::BROADCAST_ALL, event, true);
    389         // notify all subscribers NIF resource RELEASED or DENIED
    390         // by setting true, we remove subscribers from the linked list
    391         mStateMachine->notifySubscribers(notification);
    392     }
    393         break;
    394 
    395     default:
    396         LOC_LOGE("%s: unrecognized event %d", whoami(), event);
    397         // no state change.
    398     }
    399 
    400     LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d",
    401              whoami(), nextState->whoami(), event);
    402     return nextState;
    403 }
    404 
    405 
    406 class AgpsAcquiredState : public AgpsState
    407 {
    408     friend class AgpsStateMachine;
    409 
    410     inline AgpsAcquiredState(AgpsStateMachine* stateMachine) :
    411         AgpsState(stateMachine)
    412     { mAcquiredState = this; }
    413 
    414     inline ~AgpsAcquiredState() {}
    415 public:
    416     virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
    417     inline virtual char* whoami() { return (char*)"AgpsAcquiredState"; }
    418 };
    419 
    420 
    421 AgpsState* AgpsAcquiredState::onRsrcEvent(AgpsRsrcStatus event, void* data)
    422 {
    423     AgpsState* nextState = this;
    424     LOC_LOGD("AgpsAcquiredState::onRsrcEvent; event:%d\n", (int)event);
    425     switch (event)
    426     {
    427     case RSRC_SUBSCRIBE:
    428     {
    429         // we already have the NIF resource, simply notify subscriber
    430         Subscriber* subscriber = (Subscriber*) data;
    431         // we have rsrc in hand, so grant it right away
    432         Notification notification(subscriber, RSRC_GRANTED, false);
    433         subscriber->notifyRsrcStatus(notification);
    434         // add subscriber to the list
    435         mStateMachine->addSubscriber(subscriber);
    436         // no state change.
    437     }
    438         break;
    439 
    440     case RSRC_UNSUBSCRIBE:
    441     {
    442         Subscriber* subscriber = (Subscriber*) data;
    443         if (subscriber->waitForCloseComplete()) {
    444             subscriber->setInactive();
    445         } else {
    446             // auto notify this subscriber of the unsubscribe
    447             Notification notification(subscriber, event, true);
    448             mStateMachine->notifySubscribers(notification);
    449         }
    450 
    451         // now check if there is any subscribers left
    452         if (!mStateMachine->hasSubscribers()) {
    453             // no more subscribers, move to RELEASED state
    454             nextState = mReleasedState;
    455 
    456             // tell connecivity service we can release NIF
    457             mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
    458         } else if (!mStateMachine->hasActiveSubscribers()) {
    459             // only inactive subscribers, move to RELEASING state
    460             nextState = mReleasingState;
    461 
    462             // tell connecivity service we can release NIF
    463             mStateMachine->sendRsrcRequest(GPS_RELEASE_AGPS_DATA_CONN);
    464         }
    465     }
    466         break;
    467 
    468     case RSRC_GRANTED:
    469         LOC_LOGW("%s: %d, RSRC_GRANTED already received", whoami(), event);
    470         // no state change.
    471         break;
    472 
    473     case RSRC_RELEASED:
    474     {
    475         LOC_LOGW("%s: %d, a force rsrc release", whoami(), event);
    476         nextState = mReleasedState;
    477         Notification notification(Notification::BROADCAST_ALL, event, true);
    478         // by setting true, we remove subscribers from the linked list
    479         mStateMachine->notifySubscribers(notification);
    480     }
    481         break;
    482 
    483     case RSRC_DENIED:
    484         // no state change.
    485         // we are expecting RELEASED.  Handling DENIED
    486         // may like break our state machine in race conditions.
    487         break;
    488 
    489     default:
    490         LOC_LOGE("%s: unrecognized event %d", whoami(), event);
    491         // no state change.
    492     }
    493 
    494     LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d",
    495              whoami(), nextState->whoami(), event);
    496     return nextState;
    497 }
    498 
    499 // AgpsPendingState
    500 class AgpsReleasingState : public AgpsState
    501 {
    502     friend class AgpsStateMachine;
    503 
    504     inline AgpsReleasingState(AgpsStateMachine* stateMachine) :
    505         AgpsState(stateMachine)
    506     { mReleasingState = this; }
    507 
    508     inline ~AgpsReleasingState() {}
    509 public:
    510     virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data);
    511     inline virtual char* whoami() {return (char*)"AgpsReleasingState";}
    512 };
    513 
    514 AgpsState* AgpsReleasingState::onRsrcEvent(AgpsRsrcStatus event, void* data)
    515 {
    516     AgpsState* nextState = this;;
    517     LOC_LOGD("AgpsReleasingState::onRsrcEvent; event:%d\n", (int)event);
    518 
    519    switch (event)
    520     {
    521     case RSRC_SUBSCRIBE:
    522     {
    523         // already requested for NIF resource,
    524         // do nothing until we get RSRC_GRANTED indication
    525         // but we need to add subscriber to the list
    526         mStateMachine->addSubscriber((Subscriber*)data);
    527         // no state change.
    528     }
    529         break;
    530 
    531     case RSRC_UNSUBSCRIBE:
    532     {
    533         Subscriber* subscriber = (Subscriber*) data;
    534         if (subscriber->waitForCloseComplete()) {
    535             subscriber->setInactive();
    536         } else {
    537             // auto notify this subscriber of the unsubscribe
    538             Notification notification(subscriber, event, true);
    539             mStateMachine->notifySubscribers(notification);
    540         }
    541 
    542         // now check if there is any subscribers left
    543         if (!mStateMachine->hasSubscribers()) {
    544             // no more subscribers, move to RELEASED state
    545             nextState = mReleasedState;
    546         }
    547     }
    548         break;
    549 
    550     case RSRC_DENIED:
    551         // A race condition subscriber unsubscribes before AFW denies resource.
    552     case RSRC_RELEASED:
    553     {
    554         nextState = mAcquiredState;
    555         Notification notification(Notification::BROADCAST_INACTIVE, event, true);
    556         // notify all subscribers that are active NIF resource RELEASE
    557         // by setting false, we keep subscribers on the linked list
    558         mStateMachine->notifySubscribers(notification);
    559 
    560         if (mStateMachine->hasActiveSubscribers()) {
    561             nextState = mPendingState;
    562             // request from connecivity service for NIF
    563             mStateMachine->sendRsrcRequest(GPS_REQUEST_AGPS_DATA_CONN);
    564         } else {
    565             nextState = mReleasedState;
    566         }
    567     }
    568         break;
    569 
    570     case RSRC_GRANTED:
    571     default:
    572         LOC_LOGE("%s: unrecognized event %d", whoami(), event);
    573         // no state change.
    574     }
    575 
    576     LOC_LOGD("onRsrcEvent, old state %s, new state %s, event %d",
    577              whoami(), nextState->whoami(), event);
    578     return nextState;
    579 }
    580 //======================================================================
    581 //Servicer
    582 //======================================================================
    583 Servicer* Servicer :: getServicer(servicerType type, void *cb_func)
    584 {
    585     LOC_LOGD(" Enter getServicer type:%d\n", (int)type);
    586     switch(type) {
    587     case servicerTypeNoCbParam:
    588         return (new Servicer(cb_func));
    589     case servicerTypeExt:
    590         return (new ExtServicer(cb_func));
    591     case servicerTypeAgps:
    592         return (new AGpsServicer(cb_func));
    593     default:
    594         return NULL;
    595     }
    596 }
    597 
    598 int Servicer :: requestRsrc(void *cb_data)
    599 {
    600     callback();
    601     return 0;
    602 }
    603 
    604 int ExtServicer :: requestRsrc(void *cb_data)
    605 {
    606     int ret=-1;
    607     LOC_LOGD("Enter ExtServicer :: requestRsrc\n");
    608     ret = callbackExt(cb_data);
    609     LOC_LOGD("Exit ExtServicer :: requestRsrc\n");
    610     return(ret);
    611 }
    612 
    613 int AGpsServicer :: requestRsrc(void *cb_data)
    614 {
    615     callbackAGps((AGpsStatus *)cb_data);
    616     return 0;
    617 }
    618 
    619 //======================================================================
    620 // AgpsStateMachine
    621 //======================================================================
    622 
    623 AgpsStateMachine::AgpsStateMachine(servicerType servType,
    624                                    void *cb_func,
    625                                    AGpsExtType type,
    626                                    bool enforceSingleSubscriber) :
    627     mStatePtr(new AgpsReleasedState(this)),mType(type),
    628     mAPN(NULL),
    629     mAPNLen(0),
    630     mBearer(AGPS_APN_BEARER_INVALID),
    631     mEnforceSingleSubscriber(enforceSingleSubscriber),
    632     mServicer(Servicer :: getServicer(servType, (void *)cb_func))
    633 {
    634     linked_list_init(&mSubscribers);
    635 
    636     // setting up mReleasedState
    637     mStatePtr->mPendingState = new AgpsPendingState(this);
    638     mStatePtr->mAcquiredState = new AgpsAcquiredState(this);
    639     mStatePtr->mReleasingState = new AgpsReleasingState(this);
    640 
    641     // setting up mAcquiredState
    642     mStatePtr->mAcquiredState->mReleasedState = mStatePtr;
    643     mStatePtr->mAcquiredState->mPendingState = mStatePtr->mPendingState;
    644     mStatePtr->mAcquiredState->mReleasingState = mStatePtr->mReleasingState;
    645 
    646     // setting up mPendingState
    647     mStatePtr->mPendingState->mAcquiredState = mStatePtr->mAcquiredState;
    648     mStatePtr->mPendingState->mReleasedState = mStatePtr;
    649     mStatePtr->mPendingState->mReleasingState = mStatePtr->mReleasingState;
    650 
    651     // setting up mReleasingState
    652     mStatePtr->mReleasingState->mReleasedState = mStatePtr;
    653     mStatePtr->mReleasingState->mPendingState = mStatePtr->mPendingState;
    654     mStatePtr->mReleasingState->mAcquiredState = mStatePtr->mAcquiredState;
    655 }
    656 
    657 AgpsStateMachine::~AgpsStateMachine()
    658 {
    659     dropAllSubscribers();
    660 
    661     // free the 3 states.  We must read out all 3 pointers first.
    662     // Otherwise we run the risk of getting pointers from already
    663     // freed memory.
    664     AgpsState* acquiredState = mStatePtr->mAcquiredState;
    665     AgpsState* releasedState = mStatePtr->mReleasedState;
    666     AgpsState* pendindState = mStatePtr->mPendingState;
    667     AgpsState* releasingState = mStatePtr->mReleasingState;
    668 
    669     delete acquiredState;
    670     delete releasedState;
    671     delete pendindState;
    672     delete releasingState;
    673     delete mServicer;
    674     linked_list_destroy(&mSubscribers);
    675 
    676     if (NULL != mAPN) {
    677         delete[] mAPN;
    678         mAPN = NULL;
    679     }
    680 }
    681 
    682 void AgpsStateMachine::setAPN(const char* apn, unsigned int len)
    683 {
    684     if (NULL != mAPN) {
    685         delete mAPN;
    686     }
    687 
    688     if (NULL != apn) {
    689         mAPN = new char[len+1];
    690         memcpy(mAPN, apn, len);
    691         mAPN[len] = NULL;
    692 
    693         mAPNLen = len;
    694     } else {
    695         mAPN = NULL;
    696         mAPNLen = 0;
    697     }
    698 }
    699 
    700 void AgpsStateMachine::onRsrcEvent(AgpsRsrcStatus event)
    701 {
    702     switch (event)
    703     {
    704     case RSRC_GRANTED:
    705     case RSRC_RELEASED:
    706     case RSRC_DENIED:
    707         mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
    708         break;
    709     default:
    710         LOC_LOGW("AgpsStateMachine: unrecognized event %d", event);
    711         break;
    712     }
    713 }
    714 
    715 void AgpsStateMachine::notifySubscribers(Notification& notification) const
    716 {
    717     if (notification.postNotifyDelete) {
    718         // just any non NULL value to get started
    719         Subscriber* s = (Subscriber*)~0;
    720         while (NULL != s) {
    721             s = NULL;
    722             // if the last param sets to true, _search will delete
    723             // the node from the list for us.  But the problem is
    724             // once that is done, _search returns, leaving the
    725             // rest of the list unprocessed.  So we need a loop.
    726             linked_list_search(mSubscribers, (void**)&s, notifySubscriber,
    727                                (void*)&notification, true);
    728             delete s;
    729         }
    730     } else {
    731         // no loop needed if it the last param sets to false, which
    732         // mean nothing gets deleted from the list.
    733         linked_list_search(mSubscribers, NULL, notifySubscriber,
    734                            (void*)&notification, false);
    735     }
    736 }
    737 
    738 void AgpsStateMachine::addSubscriber(Subscriber* subscriber) const
    739 {
    740     Subscriber* s = NULL;
    741     Notification notification((const Subscriber*)subscriber);
    742     linked_list_search(mSubscribers, (void**)&s,
    743                        hasSubscriber, (void*)&notification, false);
    744 
    745     if (NULL == s) {
    746         linked_list_add(mSubscribers, subscriber->clone(), deleteObj);
    747     }
    748 }
    749 
    750 int AgpsStateMachine::sendRsrcRequest(AGpsStatusValue action) const
    751 {
    752     Subscriber* s = NULL;
    753     Notification notification(Notification::BROADCAST_ACTIVE);
    754     linked_list_search(mSubscribers, (void**)&s, hasSubscriber,
    755                        (void*)&notification, false);
    756 
    757     if ((NULL == s) == (GPS_RELEASE_AGPS_DATA_CONN == action)) {
    758         AGpsExtStatus nifRequest;
    759         nifRequest.size = sizeof(nifRequest);
    760         nifRequest.type = mType;
    761         nifRequest.status = action;
    762 
    763         if (s == NULL) {
    764             nifRequest.ipv4_addr = INADDR_NONE;
    765             memset(&nifRequest.addr, 0,  sizeof(nifRequest.addr));
    766             nifRequest.ssid[0] = '\0';
    767             nifRequest.password[0] = '\0';
    768         } else {
    769             s->setIPAddresses(nifRequest.addr);
    770             s->setWifiInfo(nifRequest.ssid, nifRequest.password);
    771         }
    772 
    773         CALLBACK_LOG_CALLFLOW("agps_cb", %s, loc_get_agps_status_name(action));
    774         mServicer->requestRsrc((void *)&nifRequest);
    775     }
    776     return 0;
    777 }
    778 
    779 void AgpsStateMachine::subscribeRsrc(Subscriber *subscriber)
    780 {
    781   if (mEnforceSingleSubscriber && hasSubscribers()) {
    782       Notification notification(Notification::BROADCAST_ALL, RSRC_DENIED, true);
    783       notifySubscriber(&notification, subscriber);
    784   } else {
    785       mStatePtr = mStatePtr->onRsrcEvent(RSRC_SUBSCRIBE, (void*)subscriber);
    786   }
    787 }
    788 
    789 bool AgpsStateMachine::unsubscribeRsrc(Subscriber *subscriber)
    790 {
    791     Subscriber* s = NULL;
    792     Notification notification((const Subscriber*)subscriber);
    793     linked_list_search(mSubscribers, (void**)&s,
    794                        hasSubscriber, (void*)&notification, false);
    795 
    796     if (NULL != s) {
    797         mStatePtr = mStatePtr->onRsrcEvent(RSRC_UNSUBSCRIBE, (void*)s);
    798         return true;
    799     }
    800     return false;
    801 }
    802 
    803 bool AgpsStateMachine::hasActiveSubscribers() const
    804 {
    805     Subscriber* s = NULL;
    806     Notification notification(Notification::BROADCAST_ACTIVE);
    807     linked_list_search(mSubscribers, (void**)&s,
    808                        hasSubscriber, (void*)&notification, false);
    809     return NULL != s;
    810 }
    811 
    812 //======================================================================
    813 // DSStateMachine
    814 //======================================================================
    815 void delay_callback(void *callbackData, int result)
    816 {
    817     if(callbackData) {
    818         DSStateMachine *DSSMInstance = (DSStateMachine *)callbackData;
    819         DSSMInstance->retryCallback();
    820     }
    821     else {
    822         LOC_LOGE(" NULL argument received. Failing.\n");
    823         goto err;
    824     }
    825 err:
    826     return;
    827 }
    828 
    829 DSStateMachine :: DSStateMachine(servicerType type, void *cb_func,
    830                                  LocEngAdapter* adapterHandle):
    831     AgpsStateMachine(type, cb_func, AGPS_TYPE_INVALID,false),
    832     mLocAdapter(adapterHandle)
    833 {
    834     LOC_LOGD("%s:%d]: New DSStateMachine\n", __func__, __LINE__);
    835     mRetries = 0;
    836 }
    837 
    838 void DSStateMachine :: retryCallback(void)
    839 {
    840     DSSubscriber *subscriber = NULL;
    841     Notification notification(Notification::BROADCAST_ACTIVE);
    842     linked_list_search(mSubscribers, (void**)&subscriber, hasSubscriber,
    843                        (void*)&notification, false);
    844     if(subscriber)
    845         mLocAdapter->requestSuplES(subscriber->ID);
    846     else
    847         LOC_LOGE("DSStateMachine :: retryCallback: No subscriber found." \
    848                  "Cannot retry data call\n");
    849     return;
    850 }
    851 
    852 int DSStateMachine :: sendRsrcRequest(AGpsStatusValue action) const
    853 {
    854     DSSubscriber* s = NULL;
    855     dsCbData cbData;
    856     int ret=-1;
    857     int connHandle=-1;
    858     LOC_LOGD("Enter DSStateMachine :: sendRsrcRequest\n");
    859     Notification notification(Notification::BROADCAST_ACTIVE);
    860     linked_list_search(mSubscribers, (void**)&s, hasSubscriber,
    861                        (void*)&notification, false);
    862     if(s) {
    863         connHandle = s->ID;
    864         LOC_LOGD("DSStateMachine :: sendRsrcRequest - subscriber found\n");
    865     }
    866     else
    867         LOC_LOGD("DSStateMachine :: sendRsrcRequest - No subscriber found\n");
    868 
    869     cbData.action = action;
    870     cbData.mAdapter = mLocAdapter;
    871     ret = mServicer->requestRsrc((void *)&cbData);
    872     //Only the request to start data call returns a success/failure
    873     //The request to stop data call will always succeed
    874     //Hence, the below block will only be executed when the
    875     //request to start the data call fails
    876     switch(ret) {
    877     case LOC_API_ADAPTER_ERR_ENGINE_BUSY:
    878         LOC_LOGD("DSStateMachine :: sendRsrcRequest - Failure returned: %d\n",ret);
    879         ((DSStateMachine *)this)->incRetries();
    880         if(mRetries > MAX_START_DATA_CALL_RETRIES) {
    881             LOC_LOGE(" Failed to start Data call. Fallback to normal ATL SUPL\n");
    882             informStatus(RSRC_DENIED, connHandle);
    883         }
    884         else {
    885             if(loc_timer_start(DATA_CALL_RETRY_DELAY_MSEC, delay_callback, (void *)this)) {
    886                 LOC_LOGE("Error: Could not start delay thread\n");
    887                 ret = -1;
    888                 goto err;
    889             }
    890         }
    891         break;
    892     case LOC_API_ADAPTER_ERR_UNSUPPORTED:
    893         LOC_LOGE("No profile found for emergency call. Fallback to normal SUPL ATL\n");
    894         informStatus(RSRC_DENIED, connHandle);
    895         break;
    896     case LOC_API_ADAPTER_ERR_SUCCESS:
    897         LOC_LOGD("%s:%d]: Request to start data call sent\n", __func__, __LINE__);
    898         break;
    899     case -1:
    900         //One of the ways this case can be encountered is if the callback function
    901         //receives a null argument, it just exits with -1 error
    902         LOC_LOGE("Error: Something went wrong somewhere. Falling back to normal SUPL ATL\n");
    903         informStatus(RSRC_DENIED, connHandle);
    904         break;
    905     default:
    906         LOC_LOGE("%s:%d]: Unrecognized return value\n", __func__, __LINE__);
    907     }
    908 err:
    909     LOC_LOGD("EXIT DSStateMachine :: sendRsrcRequest; ret = %d\n", ret);
    910     return ret;
    911 }
    912 
    913 void DSStateMachine :: onRsrcEvent(AgpsRsrcStatus event)
    914 {
    915     void* currState = (void *)mStatePtr;
    916     LOC_LOGD("Enter DSStateMachine :: onRsrcEvent. event = %d\n", (int)event);
    917     switch (event)
    918     {
    919     case RSRC_GRANTED:
    920         LOC_LOGD("DSStateMachine :: onRsrcEvent RSRC_GRANTED\n");
    921         mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
    922         break;
    923     case RSRC_RELEASED:
    924         LOC_LOGD("DSStateMachine :: onRsrcEvent RSRC_RELEASED\n");
    925         mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
    926         //To handle the case where we get a RSRC_RELEASED in
    927         //pending state, we translate that to a RSRC_DENIED state
    928         //since the callback from DSI is either RSRC_GRANTED or RSRC_RELEASED
    929         //for when the call is connected or disconnected respectively.
    930         if((void *)mStatePtr != currState)
    931             break;
    932         else {
    933             event = RSRC_DENIED;
    934             LOC_LOGE(" Switching event to RSRC_DENIED\n");
    935         }
    936     case RSRC_DENIED:
    937         mStatePtr = mStatePtr->onRsrcEvent(event, NULL);
    938         break;
    939     default:
    940         LOC_LOGW("AgpsStateMachine: unrecognized event %d", event);
    941         break;
    942     }
    943     LOC_LOGD("Exit DSStateMachine :: onRsrcEvent. event = %d\n", (int)event);
    944 }
    945 
    946 void DSStateMachine :: informStatus(AgpsRsrcStatus status, int ID) const
    947 {
    948     LOC_LOGD("DSStateMachine :: informStatus. Status=%d\n",(int)status);
    949     switch(status) {
    950     case RSRC_UNSUBSCRIBE:
    951         mLocAdapter->atlCloseStatus(ID, 1);
    952         break;
    953     case RSRC_RELEASED:
    954         mLocAdapter->closeDataCall();
    955         break;
    956     case RSRC_DENIED:
    957         ((DSStateMachine *)this)->mRetries = 0;
    958         mLocAdapter->requestATL(ID, AGPS_TYPE_SUPL);
    959         break;
    960     case RSRC_GRANTED:
    961         mLocAdapter->atlOpenStatus(ID, 1,
    962                                                      NULL,
    963                                                      AGPS_APN_BEARER_INVALID,
    964                                                      AGPS_TYPE_INVALID);
    965         break;
    966     default:
    967         LOC_LOGW("DSStateMachine :: informStatus - unknown status");
    968     }
    969     return;
    970 }
    971