Home | History | Annotate | Download | only in location
      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