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