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 #define LOG_TAG "LocSvc_LocationAPI" 29 30 #include <location_interface.h> 31 #include <dlfcn.h> 32 #include <platform_lib_log_util.h> 33 #include <pthread.h> 34 #include <map> 35 36 typedef void* (getLocationInterface)(); 37 typedef std::map<LocationAPI*, LocationCallbacks> LocationClientMap; 38 typedef struct { 39 LocationClientMap clientData; 40 LocationControlAPI* controlAPI; 41 LocationControlCallbacks controlCallbacks; 42 GnssInterface* gnssInterface; 43 GeofenceInterface* geofenceInterface; 44 FlpInterface* flpInterface; 45 } LocationAPIData; 46 static LocationAPIData gData = {}; 47 static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER; 48 static bool gGnssLoadFailed = false; 49 static bool gFlpLoadFailed = false; 50 static bool gGeofenceLoadFailed = false; 51 52 static bool needsGnssTrackingInfo(LocationCallbacks& locationCallbacks) 53 { 54 return (locationCallbacks.gnssLocationInfoCb != nullptr || 55 locationCallbacks.gnssSvCb != nullptr || 56 locationCallbacks.gnssNmeaCb != nullptr || 57 locationCallbacks.gnssMeasurementsCb != nullptr); 58 } 59 60 static bool isGnssClient(LocationCallbacks& locationCallbacks) 61 { 62 return (locationCallbacks.gnssNiCb != nullptr || 63 locationCallbacks.trackingCb != nullptr || 64 locationCallbacks.gnssMeasurementsCb != nullptr); 65 } 66 67 static bool isFlpClient(LocationCallbacks& locationCallbacks) 68 { 69 return (locationCallbacks.trackingCb != nullptr || 70 locationCallbacks.batchingCb != nullptr); 71 } 72 73 static bool isGeofenceClient(LocationCallbacks& locationCallbacks) 74 { 75 return (locationCallbacks.geofenceBreachCb != nullptr || 76 locationCallbacks.geofenceStatusCb != nullptr); 77 } 78 79 static void* loadLocationInterface(const char* library, const char* name) { 80 LOC_LOGD("%s]: loading %s::%s ...", __func__, library, name); 81 if (NULL == library || NULL == name) { 82 return NULL; 83 } 84 getLocationInterface* getter = NULL; 85 const char *error = NULL; 86 dlerror(); 87 void *handle = dlopen(library, RTLD_NOW); 88 if (NULL == handle || (error = dlerror()) != NULL) { 89 LOC_LOGW("dlopen for %s failed, error = %s", library, error); 90 } else { 91 getter = (getLocationInterface*)dlsym(handle, name); 92 if ((error = dlerror()) != NULL) { 93 LOC_LOGW("dlsym for %s::%s failed, error = %s", library, name, error); 94 getter = NULL; 95 } 96 } 97 98 if (NULL == getter) { 99 return (void*)getter; 100 } else { 101 return (*getter)(); 102 } 103 } 104 105 LocationAPI* 106 LocationAPI::createInstance(LocationCallbacks& locationCallbacks) 107 { 108 if (nullptr == locationCallbacks.capabilitiesCb || 109 nullptr == locationCallbacks.responseCb || 110 nullptr == locationCallbacks.collectiveResponseCb) { 111 return NULL; 112 } 113 114 LocationAPI* newLocationAPI = new LocationAPI(); 115 bool requestedCapabilities = false; 116 117 pthread_mutex_lock(&gDataMutex); 118 119 if (isGnssClient(locationCallbacks)) { 120 if (NULL == gData.gnssInterface && !gGnssLoadFailed) { 121 gData.gnssInterface = 122 (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); 123 if (NULL == gData.gnssInterface) { 124 gGnssLoadFailed = true; 125 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); 126 } else { 127 gData.gnssInterface->initialize(); 128 } 129 } 130 if (NULL != gData.gnssInterface) { 131 gData.gnssInterface->addClient(newLocationAPI, locationCallbacks); 132 if (!requestedCapabilities) { 133 gData.gnssInterface->requestCapabilities(newLocationAPI); 134 requestedCapabilities = true; 135 } 136 } 137 } 138 139 if (isFlpClient(locationCallbacks)) { 140 if (NULL == gData.flpInterface && !gFlpLoadFailed) { 141 gData.flpInterface = 142 (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface"); 143 if (NULL == gData.flpInterface) { 144 gFlpLoadFailed = true; 145 LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__); 146 } else { 147 gData.flpInterface->initialize(); 148 } 149 } 150 if (NULL != gData.flpInterface) { 151 gData.flpInterface->addClient(newLocationAPI, locationCallbacks); 152 if (!requestedCapabilities) { 153 gData.flpInterface->requestCapabilities(newLocationAPI); 154 requestedCapabilities = true; 155 } 156 } 157 } 158 159 if (isGeofenceClient(locationCallbacks)) { 160 if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) { 161 gData.geofenceInterface = 162 (GeofenceInterface*)loadLocationInterface("libgeofence.so", "getGeofenceInterface"); 163 if (NULL == gData.geofenceInterface) { 164 gGeofenceLoadFailed = true; 165 LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__); 166 } else { 167 gData.geofenceInterface->initialize(); 168 } 169 } 170 if (NULL != gData.geofenceInterface) { 171 gData.geofenceInterface->addClient(newLocationAPI, locationCallbacks); 172 if (!requestedCapabilities) { 173 gData.geofenceInterface->requestCapabilities(newLocationAPI); 174 requestedCapabilities = true; 175 } 176 } 177 } 178 179 gData.clientData[newLocationAPI] = locationCallbacks; 180 181 pthread_mutex_unlock(&gDataMutex); 182 183 return newLocationAPI; 184 } 185 186 void 187 LocationAPI::destroy() 188 { 189 delete this; 190 } 191 192 LocationAPI::LocationAPI() 193 { 194 LOC_LOGD("LOCATION API CONSTRUCTOR"); 195 } 196 197 LocationAPI::~LocationAPI() 198 { 199 LOC_LOGD("LOCATION API DESTRUCTOR"); 200 pthread_mutex_lock(&gDataMutex); 201 202 auto it = gData.clientData.find(this); 203 if (it != gData.clientData.end()) { 204 if (isGnssClient(it->second) && NULL != gData.gnssInterface) { 205 gData.gnssInterface->removeClient(it->first); 206 } 207 if (isFlpClient(it->second) && NULL != gData.flpInterface) { 208 gData.flpInterface->removeClient(it->first); 209 } 210 if (isGeofenceClient(it->second) && NULL != gData.geofenceInterface) { 211 gData.geofenceInterface->removeClient(it->first); 212 } 213 gData.clientData.erase(it); 214 } else { 215 LOC_LOGE("%s:%d]: Location API client %p not found in client data", 216 __func__, __LINE__, this); 217 } 218 219 pthread_mutex_unlock(&gDataMutex); 220 } 221 222 void 223 LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks) 224 { 225 if (nullptr == locationCallbacks.capabilitiesCb || 226 nullptr == locationCallbacks.responseCb || 227 nullptr == locationCallbacks.collectiveResponseCb) { 228 return; 229 } 230 231 pthread_mutex_lock(&gDataMutex); 232 233 if (isGnssClient(locationCallbacks)) { 234 if (NULL == gData.gnssInterface && !gGnssLoadFailed) { 235 gData.gnssInterface = 236 (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); 237 if (NULL == gData.gnssInterface) { 238 gGnssLoadFailed = true; 239 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); 240 } else { 241 gData.gnssInterface->initialize(); 242 } 243 } 244 if (NULL != gData.gnssInterface) { 245 // either adds new Client or updates existing Client 246 gData.gnssInterface->addClient(this, locationCallbacks); 247 } 248 } 249 250 if (isFlpClient(locationCallbacks)) { 251 if (NULL == gData.flpInterface && !gFlpLoadFailed) { 252 gData.flpInterface = 253 (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface"); 254 if (NULL == gData.flpInterface) { 255 gFlpLoadFailed = true; 256 LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__); 257 } else { 258 gData.flpInterface->initialize(); 259 } 260 } 261 if (NULL != gData.flpInterface) { 262 // either adds new Client or updates existing Client 263 gData.flpInterface->addClient(this, locationCallbacks); 264 } 265 } 266 267 if (isGeofenceClient(locationCallbacks)) { 268 if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) { 269 gData.geofenceInterface = 270 (GeofenceInterface*)loadLocationInterface("libgeofence.so", "getGeofenceInterface"); 271 if (NULL == gData.geofenceInterface) { 272 gGeofenceLoadFailed = true; 273 LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__); 274 } else { 275 gData.geofenceInterface->initialize(); 276 } 277 } 278 if (NULL != gData.geofenceInterface) { 279 // either adds new Client or updates existing Client 280 gData.geofenceInterface->addClient(this, locationCallbacks); 281 } 282 } 283 284 gData.clientData[this] = locationCallbacks; 285 286 pthread_mutex_unlock(&gDataMutex); 287 } 288 289 uint32_t 290 LocationAPI::startTracking(LocationOptions& locationOptions) 291 { 292 uint32_t id = 0; 293 pthread_mutex_lock(&gDataMutex); 294 295 auto it = gData.clientData.find(this); 296 if (it != gData.clientData.end()) { 297 if (gData.flpInterface != NULL && locationOptions.minDistance > 0) { 298 id = gData.flpInterface->startTracking(this, locationOptions); 299 } else if (gData.gnssInterface != NULL && needsGnssTrackingInfo(it->second)) { 300 id = gData.gnssInterface->startTracking(this, locationOptions); 301 } else if (gData.flpInterface != NULL) { 302 id = gData.flpInterface->startTracking(this, locationOptions); 303 } else if (gData.gnssInterface != NULL) { 304 id = gData.gnssInterface->startTracking(this, locationOptions); 305 } else { 306 LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ", 307 __func__, __LINE__, this); 308 } 309 } else { 310 LOC_LOGE("%s:%d]: Location API client %p not found in client data", 311 __func__, __LINE__, this); 312 } 313 314 pthread_mutex_unlock(&gDataMutex); 315 return id; 316 } 317 318 void 319 LocationAPI::stopTracking(uint32_t id) 320 { 321 pthread_mutex_lock(&gDataMutex); 322 323 auto it = gData.clientData.find(this); 324 if (it != gData.clientData.end()) { 325 // we don't know if tracking was started on flp or gnss, so we call stop on both, where 326 // stopTracking call to the incorrect interface will fail without response back to client 327 if (gData.gnssInterface != NULL) { 328 gData.gnssInterface->stopTracking(this, id); 329 } 330 if (gData.flpInterface != NULL) { 331 gData.flpInterface->stopTracking(this, id); 332 } 333 if (gData.flpInterface == NULL && gData.gnssInterface == NULL) { 334 LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ", 335 __func__, __LINE__, this); 336 } 337 } else { 338 LOC_LOGE("%s:%d]: Location API client %p not found in client data", 339 __func__, __LINE__, this); 340 } 341 342 pthread_mutex_unlock(&gDataMutex); 343 } 344 345 void 346 LocationAPI::updateTrackingOptions(uint32_t id, LocationOptions& locationOptions) 347 { 348 pthread_mutex_lock(&gDataMutex); 349 350 auto it = gData.clientData.find(this); 351 if (it != gData.clientData.end()) { 352 // we don't know if tracking was started on flp or gnss, so we call update on both, where 353 // updateTracking call to the incorrect interface will fail without response back to client 354 if (gData.gnssInterface != NULL) { 355 gData.gnssInterface->updateTrackingOptions(this, id, locationOptions); 356 } 357 if (gData.flpInterface != NULL) { 358 gData.flpInterface->updateTrackingOptions(this, id, locationOptions); 359 } 360 if (gData.flpInterface == NULL && gData.gnssInterface == NULL) { 361 LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ", 362 __func__, __LINE__, this); 363 } 364 } else { 365 LOC_LOGE("%s:%d]: Location API client %p not found in client data", 366 __func__, __LINE__, this); 367 } 368 369 pthread_mutex_unlock(&gDataMutex); 370 } 371 372 uint32_t 373 LocationAPI::startBatching(LocationOptions& locationOptions, BatchingOptions &batchingOptions) 374 { 375 uint32_t id = 0; 376 pthread_mutex_lock(&gDataMutex); 377 378 if (gData.flpInterface != NULL) { 379 id = gData.flpInterface->startBatching(this, locationOptions, batchingOptions); 380 } else { 381 LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", 382 __func__, __LINE__, this); 383 } 384 385 pthread_mutex_unlock(&gDataMutex); 386 return id; 387 } 388 389 void 390 LocationAPI::stopBatching(uint32_t id) 391 { 392 pthread_mutex_lock(&gDataMutex); 393 394 if (gData.flpInterface != NULL) { 395 gData.flpInterface->stopBatching(this, id); 396 } else { 397 LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", 398 __func__, __LINE__, this); 399 } 400 401 pthread_mutex_unlock(&gDataMutex); 402 } 403 404 void 405 LocationAPI::updateBatchingOptions(uint32_t id, 406 LocationOptions& locationOptions, BatchingOptions& batchOptions) 407 { 408 pthread_mutex_lock(&gDataMutex); 409 410 if (gData.flpInterface != NULL) { 411 gData.flpInterface->updateBatchingOptions(this, 412 id, 413 locationOptions, 414 batchOptions); 415 } else { 416 LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", 417 __func__, __LINE__, this); 418 } 419 420 pthread_mutex_unlock(&gDataMutex); 421 } 422 423 void 424 LocationAPI::getBatchedLocations(uint32_t id, size_t count) 425 { 426 pthread_mutex_lock(&gDataMutex); 427 428 if (gData.flpInterface != NULL) { 429 gData.flpInterface->getBatchedLocations(this, id, count); 430 } else { 431 LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", 432 __func__, __LINE__, this); 433 } 434 435 pthread_mutex_unlock(&gDataMutex); 436 } 437 438 uint32_t* 439 LocationAPI::addGeofences(size_t count, GeofenceOption* options, GeofenceInfo* info) 440 { 441 uint32_t* ids = NULL; 442 pthread_mutex_lock(&gDataMutex); 443 444 if (gData.geofenceInterface != NULL) { 445 ids = gData.geofenceInterface->addGeofences(this, count, options, info); 446 } else { 447 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", 448 __func__, __LINE__, this); 449 } 450 451 pthread_mutex_unlock(&gDataMutex); 452 return ids; 453 } 454 455 void 456 LocationAPI::removeGeofences(size_t count, uint32_t* ids) 457 { 458 pthread_mutex_lock(&gDataMutex); 459 460 if (gData.geofenceInterface != NULL) { 461 gData.geofenceInterface->removeGeofences(this, count, ids); 462 } else { 463 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", 464 __func__, __LINE__, this); 465 } 466 467 pthread_mutex_unlock(&gDataMutex); 468 } 469 470 void 471 LocationAPI::modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options) 472 { 473 pthread_mutex_lock(&gDataMutex); 474 475 if (gData.geofenceInterface != NULL) { 476 gData.geofenceInterface->modifyGeofences(this, count, ids, options); 477 } else { 478 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", 479 __func__, __LINE__, this); 480 } 481 482 pthread_mutex_unlock(&gDataMutex); 483 } 484 485 void 486 LocationAPI::pauseGeofences(size_t count, uint32_t* ids) 487 { 488 pthread_mutex_lock(&gDataMutex); 489 490 if (gData.geofenceInterface != NULL) { 491 gData.geofenceInterface->pauseGeofences(this, count, ids); 492 } else { 493 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", 494 __func__, __LINE__, this); 495 } 496 497 pthread_mutex_unlock(&gDataMutex); 498 } 499 500 void 501 LocationAPI::resumeGeofences(size_t count, uint32_t* ids) 502 { 503 pthread_mutex_lock(&gDataMutex); 504 505 if (gData.geofenceInterface != NULL) { 506 gData.geofenceInterface->resumeGeofences(this, count, ids); 507 } else { 508 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", 509 __func__, __LINE__, this); 510 } 511 512 pthread_mutex_unlock(&gDataMutex); 513 } 514 515 void 516 LocationAPI::gnssNiResponse(uint32_t id, GnssNiResponse response) 517 { 518 pthread_mutex_lock(&gDataMutex); 519 520 if (gData.gnssInterface != NULL) { 521 gData.gnssInterface->gnssNiResponse(this, id, response); 522 } else { 523 LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ", 524 __func__, __LINE__, this); 525 } 526 527 pthread_mutex_unlock(&gDataMutex); 528 } 529 530 LocationControlAPI* 531 LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks) 532 { 533 LocationControlAPI* controlAPI = NULL; 534 pthread_mutex_lock(&gDataMutex); 535 536 if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) { 537 if (NULL == gData.gnssInterface && !gGnssLoadFailed) { 538 gData.gnssInterface = 539 (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); 540 if (NULL == gData.gnssInterface) { 541 gGnssLoadFailed = true; 542 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); 543 } else { 544 gData.gnssInterface->initialize(); 545 } 546 } 547 if (NULL != gData.gnssInterface) { 548 gData.controlAPI = new LocationControlAPI(); 549 gData.controlCallbacks = locationControlCallbacks; 550 gData.gnssInterface->setControlCallbacks(locationControlCallbacks); 551 controlAPI = gData.controlAPI; 552 } 553 } 554 555 pthread_mutex_unlock(&gDataMutex); 556 return controlAPI; 557 } 558 559 void 560 LocationControlAPI::destroy() 561 { 562 delete this; 563 } 564 565 LocationControlAPI::LocationControlAPI() 566 { 567 LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR"); 568 } 569 570 LocationControlAPI::~LocationControlAPI() 571 { 572 LOC_LOGD("LOCATION CONTROL API DESTRUCTOR"); 573 pthread_mutex_lock(&gDataMutex); 574 575 gData.controlAPI = NULL; 576 577 pthread_mutex_unlock(&gDataMutex); 578 } 579 580 uint32_t 581 LocationControlAPI::enable(LocationTechnologyType techType) 582 { 583 uint32_t id = 0; 584 pthread_mutex_lock(&gDataMutex); 585 586 if (gData.gnssInterface != NULL) { 587 id = gData.gnssInterface->enable(techType); 588 } else { 589 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ", 590 __func__, __LINE__, this); 591 } 592 593 pthread_mutex_unlock(&gDataMutex); 594 return id; 595 } 596 597 void 598 LocationControlAPI::disable(uint32_t id) 599 { 600 pthread_mutex_lock(&gDataMutex); 601 602 if (gData.gnssInterface != NULL) { 603 gData.gnssInterface->disable(id); 604 } else { 605 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ", 606 __func__, __LINE__, this); 607 } 608 609 pthread_mutex_unlock(&gDataMutex); 610 } 611 612 uint32_t* 613 LocationControlAPI::gnssUpdateConfig(GnssConfig config) 614 { 615 uint32_t* ids = NULL; 616 pthread_mutex_lock(&gDataMutex); 617 618 if (gData.gnssInterface != NULL) { 619 ids = gData.gnssInterface->gnssUpdateConfig(config); 620 } else { 621 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ", 622 __func__, __LINE__, this); 623 } 624 625 pthread_mutex_unlock(&gDataMutex); 626 return ids; 627 } 628 629 uint32_t 630 LocationControlAPI::gnssDeleteAidingData(GnssAidingData& data) 631 { 632 uint32_t id = 0; 633 pthread_mutex_lock(&gDataMutex); 634 635 if (gData.gnssInterface != NULL) { 636 id = gData.gnssInterface->gnssDeleteAidingData(data); 637 } else { 638 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ", 639 __func__, __LINE__, this); 640 } 641 642 pthread_mutex_unlock(&gDataMutex); 643 return id; 644 } 645