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 
needsGnssTrackingInfo(LocationCallbacks & locationCallbacks)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 
isGnssClient(LocationCallbacks & locationCallbacks)60 static bool isGnssClient(LocationCallbacks& locationCallbacks)
61 {
62     return (locationCallbacks.gnssNiCb != nullptr ||
63             locationCallbacks.trackingCb != nullptr ||
64             locationCallbacks.gnssMeasurementsCb != nullptr);
65 }
66 
isFlpClient(LocationCallbacks & locationCallbacks)67 static bool isFlpClient(LocationCallbacks& locationCallbacks)
68 {
69     return (locationCallbacks.trackingCb != nullptr ||
70             locationCallbacks.batchingCb != nullptr);
71 }
72 
isGeofenceClient(LocationCallbacks & locationCallbacks)73 static bool isGeofenceClient(LocationCallbacks& locationCallbacks)
74 {
75     return (locationCallbacks.geofenceBreachCb != nullptr ||
76             locationCallbacks.geofenceStatusCb != nullptr);
77 }
78 
loadLocationInterface(const char * library,const char * name)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*
createInstance(LocationCallbacks & locationCallbacks)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
destroy()187 LocationAPI::destroy()
188 {
189     delete this;
190 }
191 
LocationAPI()192 LocationAPI::LocationAPI()
193 {
194     LOC_LOGD("LOCATION API CONSTRUCTOR");
195 }
196 
~LocationAPI()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
updateCallbacks(LocationCallbacks & locationCallbacks)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
startTracking(LocationOptions & locationOptions)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
stopTracking(uint32_t id)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
updateTrackingOptions(uint32_t id,LocationOptions & locationOptions)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
startBatching(LocationOptions & locationOptions)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
stopBatching(uint32_t id)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
updateBatchingOptions(uint32_t id,LocationOptions & locationOptions)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
getBatchedLocations(uint32_t id,size_t count)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*
addGeofences(size_t count,GeofenceOption * options,GeofenceInfo * info)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
removeGeofences(size_t count,uint32_t * ids)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
modifyGeofences(size_t count,uint32_t * ids,GeofenceOption * options)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
pauseGeofences(size_t count,uint32_t * ids)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
resumeGeofences(size_t count,uint32_t * ids)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
gnssNiResponse(uint32_t id,GnssNiResponse response)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*
createInstance(LocationControlCallbacks & locationControlCallbacks)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
destroy()558 LocationControlAPI::destroy()
559 {
560     delete this;
561 }
562 
LocationControlAPI()563 LocationControlAPI::LocationControlAPI()
564 {
565     LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR");
566 }
567 
~LocationControlAPI()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
enable(LocationTechnologyType techType)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
disable(uint32_t id)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*
gnssUpdateConfig(GnssConfig config)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
gnssDeleteAidingData(GnssAidingData & data)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