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