1 /* Copyright (c) 2017 The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 #define LOG_TAG "LocSvc_LocationAPI"
29
30 #include <location_interface.h>
31 #include <dlfcn.h>
32 #include <platform_lib_log_util.h>
33 #include <pthread.h>
34 #include <map>
35
36 typedef void* (getLocationInterface)();
37 typedef std::map<LocationAPI*, LocationCallbacks> LocationClientMap;
38 typedef struct {
39 LocationClientMap clientData;
40 LocationControlAPI* controlAPI;
41 LocationControlCallbacks controlCallbacks;
42 GnssInterface* gnssInterface;
43 GeofenceInterface* geofenceInterface;
44 FlpInterface* flpInterface;
45 } LocationAPIData;
46 static LocationAPIData gData = {};
47 static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER;
48 static bool gGnssLoadFailed = false;
49 static bool gFlpLoadFailed = false;
50 static bool gGeofenceLoadFailed = false;
51
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,BatchingOptions & batchingOptions)373 LocationAPI::startBatching(LocationOptions& locationOptions, BatchingOptions &batchingOptions)
374 {
375 uint32_t id = 0;
376 pthread_mutex_lock(&gDataMutex);
377
378 if (gData.flpInterface != NULL) {
379 id = gData.flpInterface->startBatching(this, locationOptions, batchingOptions);
380 } else {
381 LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
382 __func__, __LINE__, this);
383 }
384
385 pthread_mutex_unlock(&gDataMutex);
386 return id;
387 }
388
389 void
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,BatchingOptions & batchOptions)405 LocationAPI::updateBatchingOptions(uint32_t id,
406 LocationOptions& locationOptions, BatchingOptions& batchOptions)
407 {
408 pthread_mutex_lock(&gDataMutex);
409
410 if (gData.flpInterface != NULL) {
411 gData.flpInterface->updateBatchingOptions(this,
412 id,
413 locationOptions,
414 batchOptions);
415 } else {
416 LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
417 __func__, __LINE__, this);
418 }
419
420 pthread_mutex_unlock(&gDataMutex);
421 }
422
423 void
getBatchedLocations(uint32_t id,size_t count)424 LocationAPI::getBatchedLocations(uint32_t id, size_t count)
425 {
426 pthread_mutex_lock(&gDataMutex);
427
428 if (gData.flpInterface != NULL) {
429 gData.flpInterface->getBatchedLocations(this, id, count);
430 } else {
431 LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
432 __func__, __LINE__, this);
433 }
434
435 pthread_mutex_unlock(&gDataMutex);
436 }
437
438 uint32_t*
addGeofences(size_t count,GeofenceOption * options,GeofenceInfo * info)439 LocationAPI::addGeofences(size_t count, GeofenceOption* options, GeofenceInfo* info)
440 {
441 uint32_t* ids = NULL;
442 pthread_mutex_lock(&gDataMutex);
443
444 if (gData.geofenceInterface != NULL) {
445 ids = gData.geofenceInterface->addGeofences(this, count, options, info);
446 } else {
447 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
448 __func__, __LINE__, this);
449 }
450
451 pthread_mutex_unlock(&gDataMutex);
452 return ids;
453 }
454
455 void
removeGeofences(size_t count,uint32_t * ids)456 LocationAPI::removeGeofences(size_t count, uint32_t* ids)
457 {
458 pthread_mutex_lock(&gDataMutex);
459
460 if (gData.geofenceInterface != NULL) {
461 gData.geofenceInterface->removeGeofences(this, count, ids);
462 } else {
463 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
464 __func__, __LINE__, this);
465 }
466
467 pthread_mutex_unlock(&gDataMutex);
468 }
469
470 void
modifyGeofences(size_t count,uint32_t * ids,GeofenceOption * options)471 LocationAPI::modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options)
472 {
473 pthread_mutex_lock(&gDataMutex);
474
475 if (gData.geofenceInterface != NULL) {
476 gData.geofenceInterface->modifyGeofences(this, count, ids, options);
477 } else {
478 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
479 __func__, __LINE__, this);
480 }
481
482 pthread_mutex_unlock(&gDataMutex);
483 }
484
485 void
pauseGeofences(size_t count,uint32_t * ids)486 LocationAPI::pauseGeofences(size_t count, uint32_t* ids)
487 {
488 pthread_mutex_lock(&gDataMutex);
489
490 if (gData.geofenceInterface != NULL) {
491 gData.geofenceInterface->pauseGeofences(this, count, ids);
492 } else {
493 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
494 __func__, __LINE__, this);
495 }
496
497 pthread_mutex_unlock(&gDataMutex);
498 }
499
500 void
resumeGeofences(size_t count,uint32_t * ids)501 LocationAPI::resumeGeofences(size_t count, uint32_t* ids)
502 {
503 pthread_mutex_lock(&gDataMutex);
504
505 if (gData.geofenceInterface != NULL) {
506 gData.geofenceInterface->resumeGeofences(this, count, ids);
507 } else {
508 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
509 __func__, __LINE__, this);
510 }
511
512 pthread_mutex_unlock(&gDataMutex);
513 }
514
515 void
gnssNiResponse(uint32_t id,GnssNiResponse response)516 LocationAPI::gnssNiResponse(uint32_t id, GnssNiResponse response)
517 {
518 pthread_mutex_lock(&gDataMutex);
519
520 if (gData.gnssInterface != NULL) {
521 gData.gnssInterface->gnssNiResponse(this, id, response);
522 } else {
523 LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
524 __func__, __LINE__, this);
525 }
526
527 pthread_mutex_unlock(&gDataMutex);
528 }
529
530 LocationControlAPI*
createInstance(LocationControlCallbacks & locationControlCallbacks)531 LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks)
532 {
533 LocationControlAPI* controlAPI = NULL;
534 pthread_mutex_lock(&gDataMutex);
535
536 if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) {
537 if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
538 gData.gnssInterface =
539 (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface");
540 if (NULL == gData.gnssInterface) {
541 gGnssLoadFailed = true;
542 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
543 } else {
544 gData.gnssInterface->initialize();
545 }
546 }
547 if (NULL != gData.gnssInterface) {
548 gData.controlAPI = new LocationControlAPI();
549 gData.controlCallbacks = locationControlCallbacks;
550 gData.gnssInterface->setControlCallbacks(locationControlCallbacks);
551 controlAPI = gData.controlAPI;
552 }
553 }
554
555 pthread_mutex_unlock(&gDataMutex);
556 return controlAPI;
557 }
558
559 void
destroy()560 LocationControlAPI::destroy()
561 {
562 delete this;
563 }
564
LocationControlAPI()565 LocationControlAPI::LocationControlAPI()
566 {
567 LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR");
568 }
569
~LocationControlAPI()570 LocationControlAPI::~LocationControlAPI()
571 {
572 LOC_LOGD("LOCATION CONTROL API DESTRUCTOR");
573 pthread_mutex_lock(&gDataMutex);
574
575 gData.controlAPI = NULL;
576
577 pthread_mutex_unlock(&gDataMutex);
578 }
579
580 uint32_t
enable(LocationTechnologyType techType)581 LocationControlAPI::enable(LocationTechnologyType techType)
582 {
583 uint32_t id = 0;
584 pthread_mutex_lock(&gDataMutex);
585
586 if (gData.gnssInterface != NULL) {
587 id = gData.gnssInterface->enable(techType);
588 } else {
589 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
590 __func__, __LINE__, this);
591 }
592
593 pthread_mutex_unlock(&gDataMutex);
594 return id;
595 }
596
597 void
disable(uint32_t id)598 LocationControlAPI::disable(uint32_t id)
599 {
600 pthread_mutex_lock(&gDataMutex);
601
602 if (gData.gnssInterface != NULL) {
603 gData.gnssInterface->disable(id);
604 } else {
605 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
606 __func__, __LINE__, this);
607 }
608
609 pthread_mutex_unlock(&gDataMutex);
610 }
611
612 uint32_t*
gnssUpdateConfig(GnssConfig config)613 LocationControlAPI::gnssUpdateConfig(GnssConfig config)
614 {
615 uint32_t* ids = NULL;
616 pthread_mutex_lock(&gDataMutex);
617
618 if (gData.gnssInterface != NULL) {
619 ids = gData.gnssInterface->gnssUpdateConfig(config);
620 } else {
621 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
622 __func__, __LINE__, this);
623 }
624
625 pthread_mutex_unlock(&gDataMutex);
626 return ids;
627 }
628
629 uint32_t
gnssDeleteAidingData(GnssAidingData & data)630 LocationControlAPI::gnssDeleteAidingData(GnssAidingData& data)
631 {
632 uint32_t id = 0;
633 pthread_mutex_lock(&gDataMutex);
634
635 if (gData.gnssInterface != NULL) {
636 id = gData.gnssInterface->gnssDeleteAidingData(data);
637 } else {
638 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
639 __func__, __LINE__, this);
640 }
641
642 pthread_mutex_unlock(&gDataMutex);
643 return id;
644 }
645