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;
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         size_t gnssClientCount = 0;
205         size_t flpClientCount = 0;
206         size_t geofenceClientCount = 0;
207         for (auto it2=gData.clientData.begin(); it2 != gData.clientData.end(); ++it2) {
208             if (isGnssClient(it2->second)) {
209                 gnssClientCount++;
210             }
211             if (isFlpClient(it2->second)) {
212                 flpClientCount++;
213             }
214             if (isGeofenceClient(it2->second)) {
215                 geofenceClientCount++;
216             }
217         }
218         if (isGnssClient(it->second) && NULL != gData.gnssInterface) {
219             gData.gnssInterface->removeClient(it->first);
220             if (1 == gnssClientCount && NULL == gData.controlAPI) {
221                 gData.gnssInterface->deinitialize();
222             }
223         }
224         if (isFlpClient(it->second) && NULL != gData.flpInterface) {
225             gData.flpInterface->removeClient(it->first);
226             if (1 == flpClientCount) {
227                 gData.flpInterface->deinitialize();
228             }
229         }
230         if (isGeofenceClient(it->second) && NULL != gData.geofenceInterface) {
231             gData.geofenceInterface->removeClient(it->first);
232             if (1 == geofenceClientCount) {
233                 gData.geofenceInterface->deinitialize();
234             }
235         }
236         gData.clientData.erase(it);
237     } else {
238         LOC_LOGE("%s:%d]: Location API client %p not found in client data",
239                  __func__, __LINE__, this);
240     }
241 
242     pthread_mutex_unlock(&gDataMutex);
243 }
244 
245 void
updateCallbacks(LocationCallbacks & locationCallbacks)246 LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks)
247 {
248     if (nullptr == locationCallbacks.capabilitiesCb ||
249         nullptr == locationCallbacks.responseCb ||
250         nullptr == locationCallbacks.collectiveResponseCb) {
251         return;
252     }
253 
254     pthread_mutex_lock(&gDataMutex);
255 
256     if (isGnssClient(locationCallbacks)) {
257         if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
258             gData.gnssInterface =
259                 (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface");
260             if (NULL == gData.gnssInterface) {
261                 gGnssLoadFailed = true;
262                 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
263             } else {
264                 gData.gnssInterface->initialize();
265             }
266         }
267         if (NULL != gData.gnssInterface) {
268             // either adds new Client or updates existing Client
269             gData.gnssInterface->addClient(this, locationCallbacks);
270         }
271     }
272 
273     if (isFlpClient(locationCallbacks)) {
274         if (NULL == gData.flpInterface && !gFlpLoadFailed) {
275             gData.flpInterface =
276                 (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface");
277             if (NULL == gData.flpInterface) {
278                 gFlpLoadFailed = true;
279                 LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__);
280             } else {
281                 gData.flpInterface->initialize();
282             }
283         }
284         if (NULL != gData.flpInterface) {
285             // either adds new Client or updates existing Client
286             gData.flpInterface->addClient(this, locationCallbacks);
287         }
288     }
289 
290     if (isGeofenceClient(locationCallbacks)) {
291         if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
292             gData.geofenceInterface =
293                 (GeofenceInterface*)loadLocationInterface("libgeofence.so", "getGeofenceInterface");
294             if (NULL == gData.geofenceInterface) {
295                 gGeofenceLoadFailed = true;
296                 LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
297             } else {
298                 gData.geofenceInterface->initialize();
299             }
300         }
301         if (NULL != gData.geofenceInterface) {
302             // either adds new Client or updates existing Client
303             gData.geofenceInterface->addClient(this, locationCallbacks);
304         }
305     }
306 
307     gData.clientData[this] = locationCallbacks;
308 
309     pthread_mutex_unlock(&gDataMutex);
310 }
311 
312 uint32_t
startTracking(LocationOptions & locationOptions)313 LocationAPI::startTracking(LocationOptions& locationOptions)
314 {
315     uint32_t id = 0;
316     pthread_mutex_lock(&gDataMutex);
317 
318     auto it = gData.clientData.find(this);
319     if (it != gData.clientData.end()) {
320         if (gData.flpInterface != NULL && locationOptions.minDistance > 0) {
321             id = gData.flpInterface->startTracking(this, locationOptions);
322         } else if (gData.gnssInterface != NULL && needsGnssTrackingInfo(it->second)) {
323             id = gData.gnssInterface->startTracking(this, locationOptions);
324         } else if (gData.flpInterface != NULL) {
325             id = gData.flpInterface->startTracking(this, locationOptions);
326         } else if (gData.gnssInterface != NULL) {
327             id = gData.gnssInterface->startTracking(this, locationOptions);
328         } else {
329             LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ",
330                      __func__, __LINE__, this);
331         }
332     } else {
333         LOC_LOGE("%s:%d]: Location API client %p not found in client data",
334                  __func__, __LINE__, this);
335     }
336 
337     pthread_mutex_unlock(&gDataMutex);
338     return id;
339 }
340 
341 void
stopTracking(uint32_t id)342 LocationAPI::stopTracking(uint32_t id)
343 {
344     pthread_mutex_lock(&gDataMutex);
345 
346     auto it = gData.clientData.find(this);
347     if (it != gData.clientData.end()) {
348         // we don't know if tracking was started on flp or gnss, so we call stop on both, where
349         // stopTracking call to the incorrect interface will fail without response back to client
350         if (gData.gnssInterface != NULL) {
351             gData.gnssInterface->stopTracking(this, id);
352         }
353         if (gData.flpInterface != NULL) {
354             gData.flpInterface->stopTracking(this, id);
355         }
356         if (gData.flpInterface != NULL && gData.gnssInterface != NULL) {
357             LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ",
358                      __func__, __LINE__, this);
359         }
360     } else {
361         LOC_LOGE("%s:%d]: Location API client %p not found in client data",
362                  __func__, __LINE__, this);
363     }
364 
365     pthread_mutex_unlock(&gDataMutex);
366 }
367 
368 void
updateTrackingOptions(uint32_t id,LocationOptions & locationOptions)369 LocationAPI::updateTrackingOptions(uint32_t id, LocationOptions& locationOptions)
370 {
371     pthread_mutex_lock(&gDataMutex);
372 
373     auto it = gData.clientData.find(this);
374     if (it != gData.clientData.end()) {
375         // we don't know if tracking was started on flp or gnss, so we call update on both, where
376         // updateTracking call to the incorrect interface will fail without response back to client
377         if (gData.gnssInterface != NULL) {
378             gData.gnssInterface->updateTrackingOptions(this, id, locationOptions);
379         }
380         if (gData.flpInterface != NULL) {
381             gData.flpInterface->updateTrackingOptions(this, id, locationOptions);
382         }
383         if (gData.flpInterface != NULL && gData.gnssInterface != NULL) {
384             LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ",
385                      __func__, __LINE__, this);
386         }
387     } else {
388         LOC_LOGE("%s:%d]: Location API client %p not found in client data",
389                  __func__, __LINE__, this);
390     }
391 
392     pthread_mutex_unlock(&gDataMutex);
393 }
394 
395 uint32_t
startBatching(LocationOptions & locationOptions)396 LocationAPI::startBatching(LocationOptions& locationOptions)
397 {
398     uint32_t id = 0;
399     pthread_mutex_lock(&gDataMutex);
400 
401     if (gData.flpInterface != NULL) {
402         id = gData.flpInterface->startBatching(this, locationOptions);
403     } else {
404         LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
405                  __func__, __LINE__, this);
406     }
407 
408     pthread_mutex_unlock(&gDataMutex);
409     return id;
410 }
411 
412 void
stopBatching(uint32_t id)413 LocationAPI::stopBatching(uint32_t id)
414 {
415     pthread_mutex_lock(&gDataMutex);
416 
417     if (gData.flpInterface != NULL) {
418         gData.flpInterface->stopBatching(this, id);
419     } else {
420         LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
421                  __func__, __LINE__, this);
422     }
423 
424     pthread_mutex_unlock(&gDataMutex);
425 }
426 
427 void
updateBatchingOptions(uint32_t id,LocationOptions & locationOptions)428 LocationAPI::updateBatchingOptions(uint32_t id, LocationOptions& locationOptions)
429 {
430     pthread_mutex_lock(&gDataMutex);
431 
432     if (gData.flpInterface != NULL) {
433         gData.flpInterface->updateBatchingOptions(this,
434                                                   id,
435                                                   locationOptions);
436     } else {
437         LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
438                  __func__, __LINE__, this);
439     }
440 
441     pthread_mutex_unlock(&gDataMutex);
442 }
443 
444 void
getBatchedLocations(uint32_t id,size_t count)445 LocationAPI::getBatchedLocations(uint32_t id, size_t count)
446 {
447     pthread_mutex_lock(&gDataMutex);
448 
449     if (gData.flpInterface != NULL) {
450         gData.flpInterface->getBatchedLocations(this, id, count);
451     } else {
452         LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
453                  __func__, __LINE__, this);
454     }
455 
456     pthread_mutex_unlock(&gDataMutex);
457 }
458 
459 uint32_t*
addGeofences(size_t count,GeofenceOption * options,GeofenceInfo * info)460 LocationAPI::addGeofences(size_t count, GeofenceOption* options, GeofenceInfo* info)
461 {
462     uint32_t* ids = NULL;
463     pthread_mutex_lock(&gDataMutex);
464 
465     if (gData.geofenceInterface != NULL) {
466         ids = gData.geofenceInterface->addGeofences(this, count, options, info);
467     } else {
468         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
469                  __func__, __LINE__, this);
470     }
471 
472     pthread_mutex_unlock(&gDataMutex);
473     return ids;
474 }
475 
476 void
removeGeofences(size_t count,uint32_t * ids)477 LocationAPI::removeGeofences(size_t count, uint32_t* ids)
478 {
479     pthread_mutex_lock(&gDataMutex);
480 
481     if (gData.geofenceInterface != NULL) {
482         gData.geofenceInterface->removeGeofences(this, count, ids);
483     } else {
484         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
485                  __func__, __LINE__, this);
486     }
487 
488     pthread_mutex_unlock(&gDataMutex);
489 }
490 
491 void
modifyGeofences(size_t count,uint32_t * ids,GeofenceOption * options)492 LocationAPI::modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options)
493 {
494     pthread_mutex_lock(&gDataMutex);
495 
496     if (gData.geofenceInterface != NULL) {
497         gData.geofenceInterface->modifyGeofences(this, count, ids, options);
498     } else {
499         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
500                  __func__, __LINE__, this);
501     }
502 
503     pthread_mutex_unlock(&gDataMutex);
504 }
505 
506 void
pauseGeofences(size_t count,uint32_t * ids)507 LocationAPI::pauseGeofences(size_t count, uint32_t* ids)
508 {
509     pthread_mutex_lock(&gDataMutex);
510 
511     if (gData.geofenceInterface != NULL) {
512         gData.geofenceInterface->pauseGeofences(this, count, ids);
513     } else {
514         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
515                  __func__, __LINE__, this);
516     }
517 
518     pthread_mutex_unlock(&gDataMutex);
519 }
520 
521 void
resumeGeofences(size_t count,uint32_t * ids)522 LocationAPI::resumeGeofences(size_t count, uint32_t* ids)
523 {
524     pthread_mutex_lock(&gDataMutex);
525 
526     if (gData.geofenceInterface != NULL) {
527         gData.geofenceInterface->resumeGeofences(this, count, ids);
528     } else {
529         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
530                  __func__, __LINE__, this);
531     }
532 
533     pthread_mutex_unlock(&gDataMutex);
534 }
535 
536 void
gnssNiResponse(uint32_t id,GnssNiResponse response)537 LocationAPI::gnssNiResponse(uint32_t id, GnssNiResponse response)
538 {
539     pthread_mutex_lock(&gDataMutex);
540 
541     if (gData.gnssInterface != NULL) {
542         gData.gnssInterface->gnssNiResponse(this, id, response);
543     } else {
544         LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
545                  __func__, __LINE__, this);
546     }
547 
548     pthread_mutex_unlock(&gDataMutex);
549 }
550 
551 LocationControlAPI*
createInstance(LocationControlCallbacks & locationControlCallbacks)552 LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks)
553 {
554     LocationControlAPI* controlAPI = NULL;
555     pthread_mutex_lock(&gDataMutex);
556 
557     if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) {
558         if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
559             gData.gnssInterface =
560                 (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface");
561             if (NULL == gData.gnssInterface) {
562                 gGnssLoadFailed = true;
563                 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
564             } else {
565                 gData.gnssInterface->initialize();
566             }
567         }
568         if (NULL != gData.gnssInterface) {
569             gData.controlAPI = new LocationControlAPI();
570             gData.controlCallbacks = locationControlCallbacks;
571             gData.gnssInterface->setControlCallbacks(locationControlCallbacks);
572             controlAPI = gData.controlAPI;
573         }
574     }
575 
576     pthread_mutex_unlock(&gDataMutex);
577     return controlAPI;
578 }
579 
580 void
destroy()581 LocationControlAPI::destroy()
582 {
583     delete this;
584 }
585 
LocationControlAPI()586 LocationControlAPI::LocationControlAPI()
587 {
588     LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR");
589 }
590 
~LocationControlAPI()591 LocationControlAPI::~LocationControlAPI()
592 {
593     LOC_LOGD("LOCATION CONTROL API DESTRUCTOR");
594     pthread_mutex_lock(&gDataMutex);
595 
596     size_t gnssClientCount = 0;
597     for (auto it=gData.clientData.begin(); it != gData.clientData.end(); ++it) {
598         if (isGnssClient(it->second)) {
599             gnssClientCount++;
600         }
601     }
602     if (gData.gnssInterface != NULL && 0 == gnssClientCount) {
603         //@todo: we might want to call gData.gnssInterface.disable before deinitialize?
604         gData.gnssInterface->deinitialize();
605     }
606     gData.controlAPI = NULL;
607 
608     pthread_mutex_unlock(&gDataMutex);
609 }
610 
611 uint32_t
enable(LocationTechnologyType techType)612 LocationControlAPI::enable(LocationTechnologyType techType)
613 {
614     uint32_t id = 0;
615     pthread_mutex_lock(&gDataMutex);
616 
617     if (gData.gnssInterface != NULL) {
618         id = gData.gnssInterface->enable(techType);
619     } else {
620         LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
621                  __func__, __LINE__, this);
622     }
623 
624     pthread_mutex_unlock(&gDataMutex);
625     return id;
626 }
627 
628 void
disable(uint32_t id)629 LocationControlAPI::disable(uint32_t id)
630 {
631     pthread_mutex_lock(&gDataMutex);
632 
633     if (gData.gnssInterface != NULL) {
634         gData.gnssInterface->disable(id);
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 }
642 
643 uint32_t*
gnssUpdateConfig(GnssConfig config)644 LocationControlAPI::gnssUpdateConfig(GnssConfig config)
645 {
646     uint32_t* ids = NULL;
647     pthread_mutex_lock(&gDataMutex);
648 
649     if (gData.gnssInterface != NULL) {
650         ids = gData.gnssInterface->gnssUpdateConfig(config);
651     } else {
652         LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
653                  __func__, __LINE__, this);
654     }
655 
656     pthread_mutex_unlock(&gDataMutex);
657     return ids;
658 }
659 
660 uint32_t
gnssDeleteAidingData(GnssAidingData & data)661 LocationControlAPI::gnssDeleteAidingData(GnssAidingData& data)
662 {
663     uint32_t id = 0;
664     pthread_mutex_lock(&gDataMutex);
665 
666     if (gData.gnssInterface != NULL) {
667         id = gData.gnssInterface->gnssDeleteAidingData(data);
668     } else {
669         LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
670                  __func__, __LINE__, this);
671     }
672 
673     pthread_mutex_unlock(&gDataMutex);
674     return id;
675 }
676