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