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 <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) 374 { 375 uint32_t id = 0; 376 pthread_mutex_lock(&gDataMutex); 377 378 if (gData.flpInterface != NULL) { 379 id = gData.flpInterface->startBatching(this, locationOptions); 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, LocationOptions& locationOptions) 406 { 407 pthread_mutex_lock(&gDataMutex); 408 409 if (gData.flpInterface != NULL) { 410 gData.flpInterface->updateBatchingOptions(this, 411 id, 412 locationOptions); 413 } else { 414 LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", 415 __func__, __LINE__, this); 416 } 417 418 pthread_mutex_unlock(&gDataMutex); 419 } 420 421 void 422 LocationAPI::getBatchedLocations(uint32_t id, size_t count) 423 { 424 pthread_mutex_lock(&gDataMutex); 425 426 if (gData.flpInterface != NULL) { 427 gData.flpInterface->getBatchedLocations(this, id, count); 428 } else { 429 LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ", 430 __func__, __LINE__, this); 431 } 432 433 pthread_mutex_unlock(&gDataMutex); 434 } 435 436 uint32_t* 437 LocationAPI::addGeofences(size_t count, GeofenceOption* options, GeofenceInfo* info) 438 { 439 uint32_t* ids = NULL; 440 pthread_mutex_lock(&gDataMutex); 441 442 if (gData.geofenceInterface != NULL) { 443 ids = gData.geofenceInterface->addGeofences(this, count, options, info); 444 } else { 445 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", 446 __func__, __LINE__, this); 447 } 448 449 pthread_mutex_unlock(&gDataMutex); 450 return ids; 451 } 452 453 void 454 LocationAPI::removeGeofences(size_t count, uint32_t* ids) 455 { 456 pthread_mutex_lock(&gDataMutex); 457 458 if (gData.geofenceInterface != NULL) { 459 gData.geofenceInterface->removeGeofences(this, count, ids); 460 } else { 461 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", 462 __func__, __LINE__, this); 463 } 464 465 pthread_mutex_unlock(&gDataMutex); 466 } 467 468 void 469 LocationAPI::modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options) 470 { 471 pthread_mutex_lock(&gDataMutex); 472 473 if (gData.geofenceInterface != NULL) { 474 gData.geofenceInterface->modifyGeofences(this, count, ids, options); 475 } else { 476 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", 477 __func__, __LINE__, this); 478 } 479 480 pthread_mutex_unlock(&gDataMutex); 481 } 482 483 void 484 LocationAPI::pauseGeofences(size_t count, uint32_t* ids) 485 { 486 pthread_mutex_lock(&gDataMutex); 487 488 if (gData.geofenceInterface != NULL) { 489 gData.geofenceInterface->pauseGeofences(this, count, ids); 490 } else { 491 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", 492 __func__, __LINE__, this); 493 } 494 495 pthread_mutex_unlock(&gDataMutex); 496 } 497 498 void 499 LocationAPI::resumeGeofences(size_t count, uint32_t* ids) 500 { 501 pthread_mutex_lock(&gDataMutex); 502 503 if (gData.geofenceInterface != NULL) { 504 gData.geofenceInterface->resumeGeofences(this, count, ids); 505 } else { 506 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ", 507 __func__, __LINE__, this); 508 } 509 510 pthread_mutex_unlock(&gDataMutex); 511 } 512 513 void 514 LocationAPI::gnssNiResponse(uint32_t id, GnssNiResponse response) 515 { 516 pthread_mutex_lock(&gDataMutex); 517 518 if (gData.gnssInterface != NULL) { 519 gData.gnssInterface->gnssNiResponse(this, id, response); 520 } else { 521 LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ", 522 __func__, __LINE__, this); 523 } 524 525 pthread_mutex_unlock(&gDataMutex); 526 } 527 528 LocationControlAPI* 529 LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks) 530 { 531 LocationControlAPI* controlAPI = NULL; 532 pthread_mutex_lock(&gDataMutex); 533 534 if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) { 535 if (NULL == gData.gnssInterface && !gGnssLoadFailed) { 536 gData.gnssInterface = 537 (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface"); 538 if (NULL == gData.gnssInterface) { 539 gGnssLoadFailed = true; 540 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__); 541 } else { 542 gData.gnssInterface->initialize(); 543 } 544 } 545 if (NULL != gData.gnssInterface) { 546 gData.controlAPI = new LocationControlAPI(); 547 gData.controlCallbacks = locationControlCallbacks; 548 gData.gnssInterface->setControlCallbacks(locationControlCallbacks); 549 controlAPI = gData.controlAPI; 550 } 551 } 552 553 pthread_mutex_unlock(&gDataMutex); 554 return controlAPI; 555 } 556 557 void 558 LocationControlAPI::destroy() 559 { 560 delete this; 561 } 562 563 LocationControlAPI::LocationControlAPI() 564 { 565 LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR"); 566 } 567 568 LocationControlAPI::~LocationControlAPI() 569 { 570 LOC_LOGD("LOCATION CONTROL API DESTRUCTOR"); 571 pthread_mutex_lock(&gDataMutex); 572 573 gData.controlAPI = NULL; 574 575 pthread_mutex_unlock(&gDataMutex); 576 } 577 578 uint32_t 579 LocationControlAPI::enable(LocationTechnologyType techType) 580 { 581 uint32_t id = 0; 582 pthread_mutex_lock(&gDataMutex); 583 584 if (gData.gnssInterface != NULL) { 585 id = gData.gnssInterface->enable(techType); 586 } else { 587 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ", 588 __func__, __LINE__, this); 589 } 590 591 pthread_mutex_unlock(&gDataMutex); 592 return id; 593 } 594 595 void 596 LocationControlAPI::disable(uint32_t id) 597 { 598 pthread_mutex_lock(&gDataMutex); 599 600 if (gData.gnssInterface != NULL) { 601 gData.gnssInterface->disable(id); 602 } else { 603 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ", 604 __func__, __LINE__, this); 605 } 606 607 pthread_mutex_unlock(&gDataMutex); 608 } 609 610 uint32_t* 611 LocationControlAPI::gnssUpdateConfig(GnssConfig config) 612 { 613 uint32_t* ids = NULL; 614 pthread_mutex_lock(&gDataMutex); 615 616 if (gData.gnssInterface != NULL) { 617 ids = gData.gnssInterface->gnssUpdateConfig(config); 618 } else { 619 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ", 620 __func__, __LINE__, this); 621 } 622 623 pthread_mutex_unlock(&gDataMutex); 624 return ids; 625 } 626 627 uint32_t 628 LocationControlAPI::gnssDeleteAidingData(GnssAidingData& data) 629 { 630 uint32_t id = 0; 631 pthread_mutex_lock(&gDataMutex); 632 633 if (gData.gnssInterface != NULL) { 634 id = gData.gnssInterface->gnssDeleteAidingData(data); 635 } else { 636 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ", 637 __func__, __LINE__, this); 638 } 639 640 pthread_mutex_unlock(&gDataMutex); 641 return id; 642 } 643