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 47static 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 56static 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 69static 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//====================================================================== 86const int Notification::BROADCAST_ALL = 0x80000000; 87const int Notification::BROADCAST_ACTIVE = 0x80000001; 88const int Notification::BROADCAST_INACTIVE = 0x80000002; 89const unsigned char DSStateMachine::MAX_START_DATA_CALL_RETRIES = 4; 90const unsigned int DSStateMachine::DATA_CALL_RETRY_DELAY_MSEC = 500; 91//====================================================================== 92// Subscriber: BITSubscriber / ATLSubscriber / WIFISubscriber 93//====================================================================== 94bool Subscriber::forMe(Notification ¬ification) 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} 106bool 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 115bool BITSubscriber::notifyRsrcStatus(Notification ¬ification) 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 146bool ATLSubscriber::notifyRsrcStatus(Notification ¬ification) 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 185bool WIFISubscriber::notifyRsrcStatus(Notification ¬ification) 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} 216bool DSSubscriber::notifyRsrcStatus(Notification ¬ification) 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} 234void DSSubscriber :: setInactive() 235{ 236 mIsInactive = true; 237 ((DSStateMachine *)mStateMachine)->informStatus(RSRC_UNSUBSCRIBE, ID); 238} 239//====================================================================== 240// AgpsState: AgpsReleasedState / AgpsPendingState / AgpsAcquiredState 241//====================================================================== 242 243// AgpsReleasedState 244class AgpsReleasedState : public AgpsState 245{ 246 friend class AgpsStateMachine; 247 248 inline AgpsReleasedState(AgpsStateMachine* stateMachine) : 249 AgpsState(stateMachine) 250 { mReleasedState = this; } 251 252 inline ~AgpsReleasedState() {} 253public: 254 virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data); 255 inline virtual char* whoami() {return (char*)"AgpsReleasedState";} 256}; 257 258AgpsState* 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 311class AgpsPendingState : public AgpsState 312{ 313 friend class AgpsStateMachine; 314 315 inline AgpsPendingState(AgpsStateMachine* stateMachine) : 316 AgpsState(stateMachine) 317 { mPendingState = this; } 318 319 inline ~AgpsPendingState() {} 320public: 321 virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data); 322 inline virtual char* whoami() {return (char*)"AgpsPendingState";} 323}; 324 325AgpsState* 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 406class AgpsAcquiredState : public AgpsState 407{ 408 friend class AgpsStateMachine; 409 410 inline AgpsAcquiredState(AgpsStateMachine* stateMachine) : 411 AgpsState(stateMachine) 412 { mAcquiredState = this; } 413 414 inline ~AgpsAcquiredState() {} 415public: 416 virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data); 417 inline virtual char* whoami() { return (char*)"AgpsAcquiredState"; } 418}; 419 420 421AgpsState* 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 500class AgpsReleasingState : public AgpsState 501{ 502 friend class AgpsStateMachine; 503 504 inline AgpsReleasingState(AgpsStateMachine* stateMachine) : 505 AgpsState(stateMachine) 506 { mReleasingState = this; } 507 508 inline ~AgpsReleasingState() {} 509public: 510 virtual AgpsState* onRsrcEvent(AgpsRsrcStatus event, void* data); 511 inline virtual char* whoami() {return (char*)"AgpsReleasingState";} 512}; 513 514AgpsState* 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//====================================================================== 583Servicer* 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 598int Servicer :: requestRsrc(void *cb_data) 599{ 600 callback(); 601 return 0; 602} 603 604int 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 613int AGpsServicer :: requestRsrc(void *cb_data) 614{ 615 callbackAGps((AGpsStatus *)cb_data); 616 return 0; 617} 618 619//====================================================================== 620// AgpsStateMachine 621//====================================================================== 622 623AgpsStateMachine::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 657AgpsStateMachine::~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 682void 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 700void 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 715void 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*)¬ification, 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*)¬ification, false); 735 } 736} 737 738void 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*)¬ification, false); 744 745 if (NULL == s) { 746 linked_list_add(mSubscribers, subscriber->clone(), deleteObj); 747 } 748} 749 750int 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*)¬ification, 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 779void AgpsStateMachine::subscribeRsrc(Subscriber *subscriber) 780{ 781 if (mEnforceSingleSubscriber && hasSubscribers()) { 782 Notification notification(Notification::BROADCAST_ALL, RSRC_DENIED, true); 783 notifySubscriber(¬ification, subscriber); 784 } else { 785 mStatePtr = mStatePtr->onRsrcEvent(RSRC_SUBSCRIBE, (void*)subscriber); 786 } 787} 788 789bool 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*)¬ification, false); 795 796 if (NULL != s) { 797 mStatePtr = mStatePtr->onRsrcEvent(RSRC_UNSUBSCRIBE, (void*)s); 798 return true; 799 } 800 return false; 801} 802 803bool AgpsStateMachine::hasActiveSubscribers() const 804{ 805 Subscriber* s = NULL; 806 Notification notification(Notification::BROADCAST_ACTIVE); 807 linked_list_search(mSubscribers, (void**)&s, 808 hasSubscriber, (void*)¬ification, false); 809 return NULL != s; 810} 811 812//====================================================================== 813// DSStateMachine 814//====================================================================== 815void 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 } 825err: 826 return; 827} 828 829DSStateMachine :: 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 838void DSStateMachine :: retryCallback(void) 839{ 840 DSSubscriber *subscriber = NULL; 841 Notification notification(Notification::BROADCAST_ACTIVE); 842 linked_list_search(mSubscribers, (void**)&subscriber, hasSubscriber, 843 (void*)¬ification, 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 852int 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*)¬ification, 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 } 908err: 909 LOC_LOGD("EXIT DSStateMachine :: sendRsrcRequest; ret = %d\n", ret); 910 return ret; 911} 912 913void 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 946void 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