1/* Copyright (c) 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#define LOG_NDDEBUG 0 30#define LOG_TAG "LocSvc_APIClientBase" 31 32#include <log_util.h> 33#include <loc_cfg.h> 34#include "LocationAPIClientBase.h" 35 36#define FLP_CONF_FILE "/vendor/etc/flp.conf" 37#define GEOFENCE_SESSION_ID -1 38 39LocationAPIClientBase::LocationAPIClientBase() : 40 mTrackingCallback(nullptr), 41 mBatchingCallback(nullptr), 42 mGeofenceBreachCallback(nullptr), 43 mLocationAPI(nullptr), 44 mLocationControlAPI(nullptr), 45 mBatchSize(-1), 46 mEnabled(false), 47 mTracking(false) 48{ 49 50 // use recursive mutex, in case callback come from the same thread 51 pthread_mutexattr_t attr; 52 pthread_mutexattr_init(&attr); 53 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 54 pthread_mutex_init(&mMutex, &attr); 55 56 for (int i = 0; i < REQUEST_MAX; i++) { 57 mRequestQueues[i] = nullptr; 58 } 59 60 memset(&mConfig, 0, sizeof(GnssConfig)); 61} 62 63void LocationAPIClientBase::locAPISetCallbacks(LocationCallbacks& locationCallbacks) 64{ 65 pthread_mutex_lock(&mMutex); 66 67 if (locationCallbacks.geofenceBreachCb != nullptr) { 68 mGeofenceBreachCallback = locationCallbacks.geofenceBreachCb; 69 locationCallbacks.geofenceBreachCb = 70 [this](GeofenceBreachNotification geofenceBreachNotification) { 71 beforeGeofenceBreachCb(geofenceBreachNotification); 72 }; 73 } 74 75 locationCallbacks.capabilitiesCb = 76 [this](LocationCapabilitiesMask capabilitiesMask) { 77 onCapabilitiesCb(capabilitiesMask); 78 }; 79 locationCallbacks.responseCb = [this](LocationError error, uint32_t id) { 80 onResponseCb(error, id); 81 }; 82 locationCallbacks.collectiveResponseCb = 83 [this](size_t count, LocationError* errors, uint32_t* ids) { 84 onCollectiveResponseCb(count, errors, ids); 85 }; 86 87 if (mLocationAPI == nullptr ) { 88 mLocationAPI = LocationAPI::createInstance(locationCallbacks); 89 } else { 90 mLocationAPI->updateCallbacks(locationCallbacks); 91 } 92 93 if (mLocationControlAPI == nullptr) { 94 LocationControlCallbacks locationControlCallbacks; 95 locationControlCallbacks.size = sizeof(LocationControlCallbacks); 96 97 locationControlCallbacks.responseCb = 98 [this](LocationError error, uint32_t id) { 99 onCtrlResponseCb(error, id); 100 }; 101 locationControlCallbacks.collectiveResponseCb = 102 [this](size_t count, LocationError* errors, uint32_t* ids) { 103 onCtrlCollectiveResponseCb(count, errors, ids); 104 }; 105 106 mLocationControlAPI = LocationControlAPI::createInstance(locationControlCallbacks); 107 } 108 109 pthread_mutex_unlock(&mMutex); 110} 111 112LocationAPIClientBase::~LocationAPIClientBase() 113{ 114 pthread_mutex_lock(&mMutex); 115 116 if (mLocationAPI) { 117 mLocationAPI->destroy(); 118 mLocationAPI = nullptr; 119 } 120 if (mLocationControlAPI) { 121 mLocationControlAPI->destroy(); 122 mLocationControlAPI = nullptr; 123 } 124 125 for (int i = 0; i < REQUEST_MAX; i++) { 126 if (mRequestQueues[i]) { 127 delete mRequestQueues[i]; 128 mRequestQueues[i] = nullptr; 129 } 130 } 131 pthread_mutex_unlock(&mMutex); 132 133 pthread_mutex_destroy(&mMutex); 134} 135 136uint32_t LocationAPIClientBase::locAPIStartTracking(LocationOptions& options) 137{ 138 uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; 139 pthread_mutex_lock(&mMutex); 140 if (mLocationAPI) { 141 if (mTracking) { 142 LOC_LOGW("%s:%d] Existing tracking session present", __FUNCTION__, __LINE__); 143 } else { 144 RequestQueue* requests = mRequestQueues[REQUEST_TRACKING]; 145 if (requests) { 146 delete requests; 147 mRequestQueues[REQUEST_TRACKING] = nullptr; 148 } 149 uint32_t session = mLocationAPI->startTracking(options); 150 LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session); 151 // onResponseCb might be called from other thread immediately after 152 // startTracking returns, so we are not going to unlock mutex 153 // until StartTrackingRequest is pushed into mRequestQueues[REQUEST_TRACKING] 154 requests = new RequestQueue(session); 155 requests->push(new StartTrackingRequest(*this)); 156 mRequestQueues[REQUEST_TRACKING] = requests; 157 mTracking = true; 158 } 159 retVal = LOCATION_ERROR_SUCCESS; 160 } 161 pthread_mutex_unlock(&mMutex); 162 163 return retVal; 164} 165 166void LocationAPIClientBase::locAPIStopTracking() 167{ 168 pthread_mutex_lock(&mMutex); 169 if (mLocationAPI) { 170 uint32_t session = 0; 171 RequestQueue* requests = mRequestQueues[REQUEST_TRACKING]; 172 if (requests) { 173 session = requests->getSession(); 174 if (session > 0) { 175 requests->push(new StopTrackingRequest(*this)); 176 mLocationAPI->stopTracking(session); 177 mTracking = false; 178 } 179 } 180 } 181 pthread_mutex_unlock(&mMutex); 182} 183 184void LocationAPIClientBase::locAPIUpdateTrackingOptions(LocationOptions& options) 185{ 186 pthread_mutex_lock(&mMutex); 187 if (mLocationAPI) { 188 uint32_t session = 0; 189 RequestQueue* requests = mRequestQueues[REQUEST_TRACKING]; 190 if (requests) { 191 session = requests->getSession(); 192 if (session > 0) { 193 requests->push(new UpdateTrackingOptionsRequest(*this)); 194 mLocationAPI->updateTrackingOptions(session, options); 195 } 196 } 197 } 198 pthread_mutex_unlock(&mMutex); 199} 200 201int32_t LocationAPIClientBase::locAPIGetBatchSize() 202{ 203 if (mBatchSize == -1) { 204 const loc_param_s_type flp_conf_param_table[] = 205 { 206 {"BATCH_SIZE", &mBatchSize, nullptr, 'n'}, 207 }; 208 UTIL_READ_CONF(FLP_CONF_FILE, flp_conf_param_table); 209 if (mBatchSize < 0) { 210 // set mBatchSize to 0 if we got an illegal value from config file 211 mBatchSize = 0; 212 } 213 } 214 return mBatchSize; 215} 216 217 218uint32_t LocationAPIClientBase::locAPIStartSession(uint32_t id, uint32_t sessionMode, 219 LocationOptions& options) 220{ 221 uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; 222 pthread_mutex_lock(&mMutex); 223 if (mLocationAPI) { 224 225 if (mSessionMap.find(id) != mSessionMap.end()) { 226 LOC_LOGE("%s:%d] session %d has already started.", __FUNCTION__, __LINE__, id); 227 retVal = LOCATION_ERROR_ALREADY_STARTED; 228 } else { 229 uint32_t trackingSession = 0; 230 uint32_t batchingSession = 0; 231 232 if (sessionMode == SESSION_MODE_ON_FIX) { 233 RequestQueue* requests = mRequestQueues[REQUEST_TRACKING]; 234 if (requests) { 235 delete requests; 236 mRequestQueues[REQUEST_TRACKING] = nullptr; 237 } 238 trackingSession = mLocationAPI->startTracking(options); 239 LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, trackingSession); 240 requests = new RequestQueue(trackingSession); 241 requests->push(new StartTrackingRequest(*this)); 242 mRequestQueues[REQUEST_TRACKING] = requests; 243 } else if (sessionMode == SESSION_MODE_ON_FULL) { 244 RequestQueue* requests = mRequestQueues[REQUEST_BATCHING]; 245 if (requests) { 246 delete requests; 247 mRequestQueues[REQUEST_BATCHING] = nullptr; 248 } 249 batchingSession = mLocationAPI->startBatching(options); 250 LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, batchingSession); 251 requests = new RequestQueue(batchingSession); 252 requests->push(new StartBatchingRequest(*this)); 253 mRequestQueues[REQUEST_BATCHING] = requests; 254 } 255 256 SessionEntity entity; 257 entity.id = id; 258 entity.trackingSession = trackingSession; 259 entity.batchingSession = batchingSession; 260 entity.sessionMode = sessionMode; 261 mSessionMap[id] = entity; 262 263 retVal = LOCATION_ERROR_SUCCESS; 264 } 265 266 } 267 pthread_mutex_unlock(&mMutex); 268 269 return retVal; 270} 271 272uint32_t LocationAPIClientBase::locAPIStopSession(uint32_t id) 273{ 274 uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; 275 pthread_mutex_lock(&mMutex); 276 if (mLocationAPI) { 277 278 if (mSessionMap.find(id) != mSessionMap.end()) { 279 SessionEntity entity = mSessionMap[id]; 280 281 uint32_t trackingSession = entity.trackingSession; 282 uint32_t batchingSession = entity.batchingSession; 283 uint32_t sMode = entity.sessionMode; 284 285 mSessionMap.erase(id); 286 287 if (sMode == SESSION_MODE_ON_FIX) { 288 RequestQueue* requests = mRequestQueues[REQUEST_TRACKING]; 289 if (requests) { 290 requests->push(new StopTrackingRequest(*this)); 291 mLocationAPI->stopTracking(trackingSession); 292 } 293 } else if (sMode == SESSION_MODE_ON_FULL) { 294 RequestQueue* requests = mRequestQueues[REQUEST_BATCHING]; 295 if (requests) { 296 requests->push(new StopBatchingRequest(*this)); 297 mLocationAPI->stopBatching(batchingSession); 298 } 299 } 300 301 retVal = LOCATION_ERROR_SUCCESS; 302 } else { 303 retVal = LOCATION_ERROR_ID_UNKNOWN; 304 LOC_LOGE("%s:%d] session %d is not exist.", __FUNCTION__, __LINE__, id); 305 } 306 307 } 308 pthread_mutex_unlock(&mMutex); 309 return retVal; 310} 311 312uint32_t LocationAPIClientBase::locAPIUpdateSessionOptions(uint32_t id, uint32_t sessionMode, 313 LocationOptions& options) 314{ 315 uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; 316 pthread_mutex_lock(&mMutex); 317 if (mLocationAPI) { 318 319 if (mSessionMap.find(id) != mSessionMap.end()) { 320 SessionEntity& entity = mSessionMap[id]; 321 322 uint32_t trackingSession = entity.trackingSession; 323 uint32_t batchingSession = entity.batchingSession; 324 uint32_t sMode = entity.sessionMode; 325 326 if (sessionMode == SESSION_MODE_ON_FIX) { 327 if (sMode == SESSION_MODE_ON_FIX) { 328 RequestQueue* requests = mRequestQueues[REQUEST_TRACKING]; 329 if (requests) { 330 requests->push(new UpdateTrackingOptionsRequest(*this)); 331 mLocationAPI->updateTrackingOptions(trackingSession, options); 332 } 333 } else if (sMode == SESSION_MODE_ON_FULL) { 334 // stop batching 335 { 336 RequestQueue* requests = mRequestQueues[REQUEST_BATCHING]; 337 if (requests) { 338 requests->push(new StopBatchingRequest(*this)); 339 mLocationAPI->stopBatching(batchingSession); 340 batchingSession = 0; 341 } 342 } 343 // start tracking 344 { 345 RequestQueue* requests = mRequestQueues[REQUEST_TRACKING]; 346 if (requests) { 347 delete requests; 348 mRequestQueues[REQUEST_TRACKING] = nullptr; 349 } 350 trackingSession = mLocationAPI->startTracking(options); 351 LOC_LOGI("%s:%d] start new session: %d", 352 __FUNCTION__, __LINE__, trackingSession); 353 requests = new RequestQueue(trackingSession); 354 requests->push(new StartTrackingRequest(*this)); 355 mRequestQueues[REQUEST_TRACKING] = requests; 356 } 357 } 358 } else if (sessionMode == SESSION_MODE_ON_FULL) { 359 if (sMode == SESSION_MODE_ON_FIX) { 360 // stop tracking 361 { 362 RequestQueue* requests = mRequestQueues[REQUEST_TRACKING]; 363 if (requests) { 364 requests->push(new StopTrackingRequest(*this)); 365 mLocationAPI->stopTracking(trackingSession); 366 trackingSession = 0; 367 } 368 } 369 // start batching 370 { 371 RequestQueue* requests = mRequestQueues[REQUEST_BATCHING]; 372 if (requests) { 373 delete requests; 374 mRequestQueues[REQUEST_BATCHING] = nullptr; 375 } 376 batchingSession = mLocationAPI->startBatching(options); 377 LOC_LOGI("%s:%d] start new session: %d", 378 __FUNCTION__, __LINE__, batchingSession); 379 requests = new RequestQueue(batchingSession); 380 requests->push(new StartBatchingRequest(*this)); 381 mRequestQueues[REQUEST_BATCHING] = requests; 382 } 383 } else if (sMode == SESSION_MODE_ON_FULL) { 384 RequestQueue* requests = mRequestQueues[REQUEST_BATCHING]; 385 requests = mRequestQueues[REQUEST_BATCHING]; 386 if (requests) { 387 requests->push(new UpdateBatchingOptionsRequest(*this)); 388 mLocationAPI->updateBatchingOptions(batchingSession, options); 389 } 390 } 391 } 392 393 entity.trackingSession = trackingSession; 394 entity.batchingSession = batchingSession; 395 entity.sessionMode = sessionMode; 396 397 retVal = LOCATION_ERROR_SUCCESS; 398 } else { 399 retVal = LOCATION_ERROR_ID_UNKNOWN; 400 LOC_LOGE("%s:%d] session %d is not exist.", __FUNCTION__, __LINE__, id); 401 } 402 403 } 404 pthread_mutex_unlock(&mMutex); 405 return retVal; 406} 407 408void LocationAPIClientBase::locAPIGetBatchedLocations(size_t count) 409{ 410 pthread_mutex_lock(&mMutex); 411 if (mLocationAPI) { 412 uint32_t session = 0; 413 RequestQueue* requests = mRequestQueues[REQUEST_BATCHING]; 414 if (requests) { 415 session = requests->getSession(); 416 if (session > 0) { 417 requests->push(new GetBatchedLocationsRequest(*this)); 418 mLocationAPI->getBatchedLocations(session, count); 419 } 420 } 421 } 422 pthread_mutex_unlock(&mMutex); 423} 424 425uint32_t LocationAPIClientBase::locAPIAddGeofences( 426 size_t count, uint32_t* ids, GeofenceOption* options, GeofenceInfo* data) 427{ 428 uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; 429 pthread_mutex_lock(&mMutex); 430 if (mLocationAPI) { 431 RequestQueue* requests = mRequestQueues[REQUEST_GEOFENCE]; 432 if (!requests) { 433 // Create a new RequestQueue for Geofenceing if we've not had one. 434 // The RequestQueue will be released when LocationAPIClientBase is released. 435 requests = new RequestQueue(GEOFENCE_SESSION_ID); 436 mRequestQueues[REQUEST_GEOFENCE] = requests; 437 } 438 uint32_t* sessions = mLocationAPI->addGeofences(count, options, data); 439 if (sessions) { 440 LOC_LOGI("%s:%d] start new sessions: %p", __FUNCTION__, __LINE__, sessions); 441 requests->push(new AddGeofencesRequest(*this)); 442 443 for (size_t i = 0; i < count; i++) { 444 mGeofenceBiDict.set(ids[i], sessions[i], options[i].breachTypeMask); 445 } 446 retVal = LOCATION_ERROR_SUCCESS; 447 } 448 } 449 pthread_mutex_unlock(&mMutex); 450 451 return retVal; 452} 453 454void LocationAPIClientBase::locAPIRemoveGeofences(size_t count, uint32_t* ids) 455{ 456 pthread_mutex_lock(&mMutex); 457 if (mLocationAPI) { 458 uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count); 459 460 RequestQueue* requests = mRequestQueues[REQUEST_GEOFENCE]; 461 if (requests) { 462 size_t j = 0; 463 for (size_t i = 0; i < count; i++) { 464 sessions[j] = mGeofenceBiDict.getSession(ids[i]); 465 if (sessions[j] > 0) { 466 j++; 467 } 468 } 469 if (j > 0) { 470 requests->push(new RemoveGeofencesRequest(*this)); 471 mLocationAPI->removeGeofences(j, sessions); 472 } 473 } 474 475 free(sessions); 476 } 477 pthread_mutex_unlock(&mMutex); 478} 479 480void LocationAPIClientBase::locAPIModifyGeofences( 481 size_t count, uint32_t* ids, GeofenceOption* options) 482{ 483 pthread_mutex_lock(&mMutex); 484 if (mLocationAPI) { 485 uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count); 486 487 RequestQueue* requests = mRequestQueues[REQUEST_GEOFENCE]; 488 if (requests) { 489 size_t j = 0; 490 for (size_t i = 0; i < count; i++) { 491 sessions[j] = mGeofenceBiDict.getSession(ids[i]); 492 if (sessions[j] > 0) { 493 mGeofenceBiDict.set(ids[i], sessions[j], options[i].breachTypeMask); 494 j++; 495 } 496 } 497 if (j > 0) { 498 requests->push(new ModifyGeofencesRequest(*this)); 499 mLocationAPI->modifyGeofences(j, sessions, options); 500 } 501 } 502 503 free(sessions); 504 } 505 pthread_mutex_unlock(&mMutex); 506} 507 508void LocationAPIClientBase::locAPIPauseGeofences(size_t count, uint32_t* ids) 509{ 510 pthread_mutex_lock(&mMutex); 511 if (mLocationAPI) { 512 uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count); 513 514 RequestQueue* requests = mRequestQueues[REQUEST_GEOFENCE]; 515 if (requests) { 516 size_t j = 0; 517 for (size_t i = 0; i < count; i++) { 518 sessions[j] = mGeofenceBiDict.getSession(ids[i]); 519 if (sessions[j] > 0) { 520 j++; 521 } 522 } 523 if (j > 0) { 524 requests->push(new PauseGeofencesRequest(*this)); 525 mLocationAPI->pauseGeofences(j, sessions); 526 } 527 } 528 529 free(sessions); 530 } 531 pthread_mutex_unlock(&mMutex); 532} 533 534void LocationAPIClientBase::locAPIResumeGeofences( 535 size_t count, uint32_t* ids, GeofenceBreachTypeMask* mask) 536{ 537 pthread_mutex_lock(&mMutex); 538 if (mLocationAPI) { 539 uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count); 540 541 RequestQueue* requests = mRequestQueues[REQUEST_GEOFENCE]; 542 if (requests) { 543 size_t j = 0; 544 for (size_t i = 0; i < count; i++) { 545 sessions[j] = mGeofenceBiDict.getSession(ids[i]); 546 if (sessions[j] > 0) { 547 if (mask) { 548 mGeofenceBiDict.set(ids[i], sessions[j], mask[i]); 549 } 550 j++; 551 } 552 } 553 if (j > 0) { 554 requests->push(new ResumeGeofencesRequest(*this)); 555 mLocationAPI->resumeGeofences(j, sessions); 556 } 557 } 558 559 free(sessions); 560 } 561 pthread_mutex_unlock(&mMutex); 562} 563 564void LocationAPIClientBase::locAPIRemoveAllGeofences() 565{ 566 pthread_mutex_lock(&mMutex); 567 if (mLocationAPI) { 568 std::vector<uint32_t> sessionsVec = mGeofenceBiDict.getAllSessions(); 569 size_t count = sessionsVec.size(); 570 uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count); 571 572 RequestQueue* requests = mRequestQueues[REQUEST_GEOFENCE]; 573 if (requests) { 574 size_t j = 0; 575 for (size_t i = 0; i < count; i++) { 576 sessions[j] = sessionsVec[i]; 577 if (sessions[j] > 0) { 578 j++; 579 } 580 } 581 if (j > 0) { 582 requests->push(new RemoveGeofencesRequest(*this)); 583 mLocationAPI->removeGeofences(j, sessions); 584 } 585 } 586 587 free(sessions); 588 } 589 pthread_mutex_unlock(&mMutex); 590} 591 592void LocationAPIClientBase::locAPIGnssNiResponse(uint32_t id, GnssNiResponse response) 593{ 594 pthread_mutex_lock(&mMutex); 595 if (mLocationAPI) { 596 RequestQueue* requests = mRequestQueues[REQUEST_NIRESPONSE]; 597 if (requests) { 598 delete requests; 599 mRequestQueues[REQUEST_NIRESPONSE] = nullptr; 600 } 601 uint32_t session = id; 602 mLocationAPI->gnssNiResponse(id, response); 603 LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session); 604 requests = new RequestQueue(session); 605 requests->push(new GnssNiResponseRequest(*this)); 606 mRequestQueues[REQUEST_NIRESPONSE] = requests; 607 } 608 pthread_mutex_unlock(&mMutex); 609} 610 611uint32_t LocationAPIClientBase::locAPIGnssDeleteAidingData(GnssAidingData& data) 612{ 613 uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; 614 pthread_mutex_lock(&mMutex); 615 if (mLocationControlAPI) { 616 RequestQueue* requests = mRequestQueues[REQUEST_DELETEAIDINGDATA]; 617 if (requests) { 618 delete requests; 619 mRequestQueues[REQUEST_DELETEAIDINGDATA] = nullptr; 620 } 621 uint32_t session = mLocationControlAPI->gnssDeleteAidingData(data); 622 LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session); 623 requests = new RequestQueue(session); 624 requests->push(new GnssDeleteAidingDataRequest(*this)); 625 mRequestQueues[REQUEST_DELETEAIDINGDATA] = requests; 626 627 retVal = LOCATION_ERROR_SUCCESS; 628 } 629 pthread_mutex_unlock(&mMutex); 630 631 return retVal; 632} 633 634uint32_t LocationAPIClientBase::locAPIEnable(LocationTechnologyType techType) 635{ 636 uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; 637 pthread_mutex_lock(&mMutex); 638 if (mEnabled) { 639 // just return success if already enabled 640 retVal = LOCATION_ERROR_SUCCESS; 641 } else if (mLocationControlAPI) { 642 RequestQueue* requests = mRequestQueues[REQUEST_CONTROL]; 643 if (requests) { 644 delete requests; 645 mRequestQueues[REQUEST_CONTROL] = nullptr; 646 } 647 uint32_t session = mLocationControlAPI->enable(techType); 648 LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session); 649 requests = new RequestQueue(session); 650 mRequestQueues[REQUEST_CONTROL] = requests; 651 if (requests) { 652 requests->push(new EnableRequest(*this)); 653 retVal = LOCATION_ERROR_SUCCESS; 654 mEnabled = true; 655 } 656 } 657 pthread_mutex_unlock(&mMutex); 658 659 return retVal; 660} 661 662void LocationAPIClientBase::locAPIDisable() 663{ 664 pthread_mutex_lock(&mMutex); 665 if (mEnabled && mLocationControlAPI) { 666 uint32_t session = 0; 667 RequestQueue* requests = mRequestQueues[REQUEST_CONTROL]; 668 if (requests) { 669 session = requests->getSession(); 670 if (session > 0) { 671 requests->push(new DisableRequest(*this)); 672 mLocationControlAPI->disable(session); 673 mEnabled = false; 674 } 675 } 676 } 677 pthread_mutex_unlock(&mMutex); 678} 679 680uint32_t LocationAPIClientBase::locAPIGnssUpdateConfig(GnssConfig config) 681{ 682 uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE; 683 if (memcmp(&mConfig, &config, sizeof(GnssConfig)) == 0) { 684 LOC_LOGV("%s:%d] GnssConfig is identical to previous call", __FUNCTION__, __LINE__); 685 retVal = LOCATION_ERROR_SUCCESS; 686 return retVal; 687 } 688 689 pthread_mutex_lock(&mMutex); 690 if (mLocationControlAPI) { 691 692 memcpy(&mConfig, &config, sizeof(GnssConfig)); 693 694 uint32_t session = 0; 695 RequestQueue* requests = mRequestQueues[REQUEST_CONFIG]; 696 uint32_t* idArray = mLocationControlAPI->gnssUpdateConfig(config); 697 LOC_LOGV("%s:%d] gnssUpdateConfig return array: %p", __FUNCTION__, __LINE__, idArray); 698 if (!requests && idArray != nullptr) { 699 requests = new RequestQueue(idArray[0]); 700 mRequestQueues[REQUEST_CONFIG] = requests; 701 } 702 if (requests) { 703 requests->push(new GnssUpdateConfigRequest(*this)); 704 retVal = LOCATION_ERROR_SUCCESS; 705 } 706 } 707 pthread_mutex_unlock(&mMutex); 708 return retVal; 709} 710 711void LocationAPIClientBase::beforeGeofenceBreachCb( 712 GeofenceBreachNotification geofenceBreachNotification) 713{ 714 if (mGeofenceBreachCallback == nullptr) 715 return; 716 uint32_t* ids = (uint32_t*)malloc(sizeof(uint32_t) * geofenceBreachNotification.count); 717 uint32_t* backup = geofenceBreachNotification.ids; 718 size_t n = geofenceBreachNotification.count; 719 720 size_t count = 0; 721 for (size_t i = 0; i < n; i++) { 722 uint32_t id = mGeofenceBiDict.getId(geofenceBreachNotification.ids[i]); 723 GeofenceBreachTypeMask type = mGeofenceBiDict.getType(geofenceBreachNotification.ids[i]); 724 // if type == 0, we will not head into the fllowing block anyway. 725 // so we don't need to check id and type 726 if ((geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER && 727 (type & GEOFENCE_BREACH_ENTER_BIT)) || 728 (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT && 729 (type & GEOFENCE_BREACH_EXIT_BIT)) 730 ) { 731 ids[count] = id; 732 count++; 733 } 734 } 735 geofenceBreachNotification.count = count; 736 geofenceBreachNotification.ids = ids; 737 mGeofenceBreachCallback(geofenceBreachNotification); 738 739 // restore ids 740 geofenceBreachNotification.ids = backup; 741 geofenceBreachNotification.count = n; 742 free(ids); 743} 744 745void LocationAPIClientBase::onResponseCb(LocationError error, uint32_t id) 746{ 747 if (error != LOCATION_ERROR_SUCCESS) { 748 LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, error, id); 749 } else { 750 LOC_LOGV("%s:%d] error: %d id: %d", __FUNCTION__, __LINE__, error, id); 751 } 752 LocationAPIRequest* request = getRequestBySession(id); 753 if (request) { 754 request->onResponse(error); 755 delete request; 756 } 757} 758 759void LocationAPIClientBase::onCollectiveResponseCb( 760 size_t count, LocationError* errors, uint32_t* ids) 761{ 762 for (size_t i = 0; i < count; i++) { 763 if (errors[i] != LOCATION_ERROR_SUCCESS) { 764 LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, errors[i], ids[i]); 765 } else { 766 LOC_LOGV("%s:%d] error: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]); 767 } 768 } 769 LocationAPIRequest* request = nullptr; 770 pthread_mutex_lock(&mMutex); 771 if (mRequestQueues[REQUEST_GEOFENCE] != nullptr) { 772 request = mRequestQueues[REQUEST_GEOFENCE]->pop(); 773 } 774 pthread_mutex_unlock(&mMutex); 775 if (request) { 776 request->onCollectiveResponse(count, errors, ids); 777 delete request; 778 } 779} 780 781void LocationAPIClientBase::onCtrlResponseCb(LocationError error, uint32_t id) 782{ 783 if (error != LOCATION_ERROR_SUCCESS) { 784 LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, error, id); 785 } else { 786 LOC_LOGV("%s:%d] error: %d id: %d", __FUNCTION__, __LINE__, error, id); 787 } 788 LocationAPIRequest* request = getRequestBySession(id); 789 if (request) { 790 request->onResponse(error); 791 delete request; 792 } 793} 794 795void LocationAPIClientBase::onCtrlCollectiveResponseCb( 796 size_t count, LocationError* errors, uint32_t* ids) 797{ 798 for (size_t i = 0; i < count; i++) { 799 if (errors[i] != LOCATION_ERROR_SUCCESS) { 800 LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, errors[i], ids[i]); 801 } else { 802 LOC_LOGV("%s:%d] error: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]); 803 } 804 } 805 LocationAPIRequest* request = nullptr; 806 pthread_mutex_lock(&mMutex); 807 if (mRequestQueues[REQUEST_CONFIG] != nullptr) { 808 request = mRequestQueues[REQUEST_CONFIG]->pop(); 809 } 810 pthread_mutex_unlock(&mMutex); 811 if (request) { 812 request->onCollectiveResponse(count, errors, ids); 813 delete request; 814 } 815} 816 817LocationAPIClientBase::LocationAPIRequest* 818LocationAPIClientBase::getRequestBySession(uint32_t session) 819{ 820 pthread_mutex_lock(&mMutex); 821 LocationAPIRequest* request = nullptr; 822 for (int i = 0; i < REQUEST_MAX; i++) { 823 if (i != REQUEST_GEOFENCE && 824 i != REQUEST_CONFIG && 825 mRequestQueues[i] && 826 mRequestQueues[i]->getSession() == session) { 827 request = mRequestQueues[i]->pop(); 828 break; 829 } 830 } 831 pthread_mutex_unlock(&mMutex); 832 return request; 833} 834