1 /* Copyright (c) 2017-2019 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_NDEBUG 0
29 #define LOG_TAG "LocSvc_LocationAPI"
30 
31 #include <location_interface.h>
32 #include <dlfcn.h>
33 #include <loc_pla.h>
34 #include <log_util.h>
35 #include <pthread.h>
36 #include <map>
37 #include <loc_misc_utils.h>
38 
39 typedef const GnssInterface* (getGnssInterface)();
40 typedef const GeofenceInterface* (getGeofenceInterface)();
41 typedef const BatchingInterface* (getBatchingInterface)();
42 
43 typedef struct {
44     // bit mask of the adpaters that we need to wait for the removeClientCompleteCallback
45     // before we invoke the registered locationApiDestroyCompleteCallback
46     LocationAdapterTypeMask waitAdapterMask;
47     locationApiDestroyCompleteCallback destroyCompleteCb;
48 } LocationAPIDestroyCbData;
49 
50 // This is the map for the client that has requested destroy with
51 // destroy callback provided.
52 typedef std::map<LocationAPI*, LocationAPIDestroyCbData>
53     LocationClientDestroyCbMap;
54 
55 typedef std::map<LocationAPI*, LocationCallbacks> LocationClientMap;
56 typedef struct {
57     LocationClientMap clientData;
58     LocationClientDestroyCbMap destroyClientData;
59     LocationControlAPI* controlAPI;
60     LocationControlCallbacks controlCallbacks;
61     GnssInterface* gnssInterface;
62     GeofenceInterface* geofenceInterface;
63     BatchingInterface* batchingInterface;
64 } LocationAPIData;
65 
66 static LocationAPIData gData = {};
67 static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER;
68 static bool gGnssLoadFailed = false;
69 static bool gBatchingLoadFailed = false;
70 static bool gGeofenceLoadFailed = false;
71 
72 template <typename T1, typename T2>
loadLocationInterface(const char * library,const char * name)73 static const T1* loadLocationInterface(const char* library, const char* name) {
74     void* libhandle = nullptr;
75     T2* getter = (T2*)dlGetSymFromLib(libhandle, library, name);
76     if (nullptr == getter) {
77         return (const T1*) getter;
78     }else {
79         return (*getter)();
80     }
81 }
82 
isGnssClient(LocationCallbacks & locationCallbacks)83 static bool isGnssClient(LocationCallbacks& locationCallbacks)
84 {
85     return (locationCallbacks.gnssNiCb != nullptr ||
86             locationCallbacks.trackingCb != nullptr ||
87             locationCallbacks.gnssLocationInfoCb != nullptr ||
88             locationCallbacks.gnssMeasurementsCb != nullptr);
89 }
90 
isBatchingClient(LocationCallbacks & locationCallbacks)91 static bool isBatchingClient(LocationCallbacks& locationCallbacks)
92 {
93     return (locationCallbacks.batchingCb != nullptr);
94 }
95 
isGeofenceClient(LocationCallbacks & locationCallbacks)96 static bool isGeofenceClient(LocationCallbacks& locationCallbacks)
97 {
98     return (locationCallbacks.geofenceBreachCb != nullptr ||
99             locationCallbacks.geofenceStatusCb != nullptr);
100 }
101 
102 
onRemoveClientCompleteCb(LocationAdapterTypeMask adapterType)103 void LocationAPI::onRemoveClientCompleteCb (LocationAdapterTypeMask adapterType)
104 {
105     bool invokeCallback = false;
106     locationApiDestroyCompleteCallback destroyCompleteCb;
107     LOC_LOGd("adatper type %x", adapterType);
108     pthread_mutex_lock(&gDataMutex);
109     auto it = gData.destroyClientData.find(this);
110     if (it != gData.destroyClientData.end()) {
111         it->second.waitAdapterMask &= ~adapterType;
112         if (it->second.waitAdapterMask == 0) {
113             invokeCallback = true;
114             destroyCompleteCb = it->second.destroyCompleteCb;
115             gData.destroyClientData.erase(it);
116         }
117     }
118     pthread_mutex_unlock(&gDataMutex);
119 
120     if ((true == invokeCallback) && (nullptr != destroyCompleteCb)) {
121         LOC_LOGd("invoke client destroy cb");
122         (destroyCompleteCb) ();
123         LOC_LOGd("finish invoke client destroy cb");
124 
125         delete this;
126     }
127 }
128 
onGnssRemoveClientCompleteCb(LocationAPI * client)129 void onGnssRemoveClientCompleteCb (LocationAPI* client)
130 {
131     client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GNSS_TYPE_BIT);
132 }
133 
onBatchingRemoveClientCompleteCb(LocationAPI * client)134 void onBatchingRemoveClientCompleteCb (LocationAPI* client)
135 {
136     client->onRemoveClientCompleteCb (LOCATION_ADAPTER_BATCHING_TYPE_BIT);
137 }
138 
onGeofenceRemoveClientCompleteCb(LocationAPI * client)139 void onGeofenceRemoveClientCompleteCb (LocationAPI* client)
140 {
141     client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GEOFENCE_TYPE_BIT);
142 }
143 
144 LocationAPI*
createInstance(LocationCallbacks & locationCallbacks)145 LocationAPI::createInstance(LocationCallbacks& locationCallbacks)
146 {
147     if (nullptr == locationCallbacks.capabilitiesCb ||
148         nullptr == locationCallbacks.responseCb ||
149         nullptr == locationCallbacks.collectiveResponseCb) {
150         return NULL;
151     }
152 
153     LocationAPI* newLocationAPI = new LocationAPI();
154     bool requestedCapabilities = false;
155 
156     pthread_mutex_lock(&gDataMutex);
157 
158     if (isGnssClient(locationCallbacks)) {
159         if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
160             gData.gnssInterface =
161                 (GnssInterface*)loadLocationInterface<GnssInterface,
162                     getGnssInterface>("libgnss.so", "getGnssInterface");
163             if (NULL == gData.gnssInterface) {
164                 gGnssLoadFailed = true;
165                 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
166             } else {
167                 gData.gnssInterface->initialize();
168             }
169         }
170         if (NULL != gData.gnssInterface) {
171             gData.gnssInterface->addClient(newLocationAPI, locationCallbacks);
172             if (!requestedCapabilities) {
173                 gData.gnssInterface->requestCapabilities(newLocationAPI);
174                 requestedCapabilities = true;
175             }
176         }
177     }
178 
179     if (isBatchingClient(locationCallbacks)) {
180         if (NULL == gData.batchingInterface && !gBatchingLoadFailed) {
181             gData.batchingInterface =
182                 (BatchingInterface*)loadLocationInterface<BatchingInterface,
183                  getBatchingInterface>("libbatching.so", "getBatchingInterface");
184             if (NULL == gData.batchingInterface) {
185                 gBatchingLoadFailed = true;
186                 LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__);
187             } else {
188                 gData.batchingInterface->initialize();
189             }
190         }
191         if (NULL != gData.batchingInterface) {
192             gData.batchingInterface->addClient(newLocationAPI, locationCallbacks);
193             if (!requestedCapabilities) {
194                 gData.batchingInterface->requestCapabilities(newLocationAPI);
195                 requestedCapabilities = true;
196             }
197         }
198     }
199 
200     if (isGeofenceClient(locationCallbacks)) {
201         if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
202             gData.geofenceInterface =
203                (GeofenceInterface*)loadLocationInterface<GeofenceInterface,
204                getGeofenceInterface>("libgeofencing.so", "getGeofenceInterface");
205             if (NULL == gData.geofenceInterface) {
206                 gGeofenceLoadFailed = true;
207                 LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
208             } else {
209                 gData.geofenceInterface->initialize();
210             }
211         }
212         if (NULL != gData.geofenceInterface) {
213             gData.geofenceInterface->addClient(newLocationAPI, locationCallbacks);
214             if (!requestedCapabilities) {
215                 gData.geofenceInterface->requestCapabilities(newLocationAPI);
216                 requestedCapabilities = true;
217             }
218         }
219     }
220 
221     gData.clientData[newLocationAPI] = locationCallbacks;
222 
223     pthread_mutex_unlock(&gDataMutex);
224 
225     return newLocationAPI;
226 }
227 
228 void
destroy(locationApiDestroyCompleteCallback destroyCompleteCb)229 LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb)
230 {
231     bool invokeDestroyCb = false;
232 
233     pthread_mutex_lock(&gDataMutex);
234     auto it = gData.clientData.find(this);
235     if (it != gData.clientData.end()) {
236         bool removeFromGnssInf =
237                 (isGnssClient(it->second) && NULL != gData.gnssInterface);
238         bool removeFromBatchingInf =
239                 (isBatchingClient(it->second) && NULL != gData.batchingInterface);
240         bool removeFromGeofenceInf =
241                 (isGeofenceClient(it->second) && NULL != gData.geofenceInterface);
242         bool needToWait = (removeFromGnssInf || removeFromBatchingInf || removeFromGeofenceInf);
243         LOC_LOGe("removeFromGnssInf: %d, removeFromBatchingInf: %d, removeFromGeofenceInf: %d,"
244                  "need %d", removeFromGnssInf, removeFromBatchingInf, removeFromGeofenceInf,
245                  needToWait);
246 
247         if ((NULL != destroyCompleteCb) && (true == needToWait)) {
248             LocationAPIDestroyCbData destroyCbData = {};
249             destroyCbData.destroyCompleteCb = destroyCompleteCb;
250             // record down from which adapter we need to wait for the destroy complete callback
251             // only when we have received all the needed callbacks from all the associated stacks,
252             // we shall notify the client.
253             destroyCbData.waitAdapterMask =
254                     (removeFromGnssInf ? LOCATION_ADAPTER_GNSS_TYPE_BIT : 0);
255             destroyCbData.waitAdapterMask |=
256                     (removeFromBatchingInf ? LOCATION_ADAPTER_BATCHING_TYPE_BIT : 0);
257             destroyCbData.waitAdapterMask |=
258                     (removeFromGeofenceInf ? LOCATION_ADAPTER_GEOFENCE_TYPE_BIT : 0);
259             gData.destroyClientData[this] = destroyCbData;
260             LOC_LOGe("destroy data stored in the map: 0x%x", destroyCbData.waitAdapterMask);
261         }
262 
263         if (removeFromGnssInf) {
264             gData.gnssInterface->removeClient(it->first,
265                                               onGnssRemoveClientCompleteCb);
266         }
267         if (removeFromBatchingInf) {
268             gData.batchingInterface->removeClient(it->first,
269                                              onBatchingRemoveClientCompleteCb);
270         }
271         if (removeFromGeofenceInf) {
272             gData.geofenceInterface->removeClient(it->first,
273                                                   onGeofenceRemoveClientCompleteCb);
274         }
275 
276         gData.clientData.erase(it);
277 
278         if ((NULL != destroyCompleteCb) && (false == needToWait)) {
279             invokeDestroyCb = true;
280         }
281     } else {
282         LOC_LOGE("%s:%d]: Location API client %p not found in client data",
283                  __func__, __LINE__, this);
284     }
285 
286     pthread_mutex_unlock(&gDataMutex);
287     if (invokeDestroyCb == true) {
288         (destroyCompleteCb) ();
289         delete this;
290     }
291 }
292 
LocationAPI()293 LocationAPI::LocationAPI()
294 {
295     LOC_LOGD("LOCATION API CONSTRUCTOR");
296 }
297 
298 // private destructor
~LocationAPI()299 LocationAPI::~LocationAPI()
300 {
301     LOC_LOGD("LOCATION API DESTRUCTOR");
302 }
303 
304 void
updateCallbacks(LocationCallbacks & locationCallbacks)305 LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks)
306 {
307     if (nullptr == locationCallbacks.capabilitiesCb ||
308         nullptr == locationCallbacks.responseCb ||
309         nullptr == locationCallbacks.collectiveResponseCb) {
310         return;
311     }
312 
313     pthread_mutex_lock(&gDataMutex);
314 
315     if (isGnssClient(locationCallbacks)) {
316         if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
317             gData.gnssInterface =
318                 (GnssInterface*)loadLocationInterface<GnssInterface,
319                     getGnssInterface>("libgnss.so", "getGnssInterface");
320             if (NULL == gData.gnssInterface) {
321                 gGnssLoadFailed = true;
322                 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
323             } else {
324                 gData.gnssInterface->initialize();
325             }
326         }
327         if (NULL != gData.gnssInterface) {
328             // either adds new Client or updates existing Client
329             gData.gnssInterface->addClient(this, locationCallbacks);
330         }
331     }
332 
333     if (isBatchingClient(locationCallbacks)) {
334         if (NULL == gData.batchingInterface && !gBatchingLoadFailed) {
335             gData.batchingInterface =
336                 (BatchingInterface*)loadLocationInterface<BatchingInterface,
337                  getBatchingInterface>("libbatching.so", "getBatchingInterface");
338             if (NULL == gData.batchingInterface) {
339                 gBatchingLoadFailed = true;
340                 LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__);
341             } else {
342                 gData.batchingInterface->initialize();
343             }
344         }
345         if (NULL != gData.batchingInterface) {
346             // either adds new Client or updates existing Client
347             gData.batchingInterface->addClient(this, locationCallbacks);
348         }
349     }
350 
351     if (isGeofenceClient(locationCallbacks)) {
352         if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
353             gData.geofenceInterface =
354                 (GeofenceInterface*)loadLocationInterface<GeofenceInterface,
355                  getGeofenceInterface>("libgeofencing.so", "getGeofenceInterface");
356             if (NULL == gData.geofenceInterface) {
357                 gGeofenceLoadFailed = true;
358                 LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
359             } else {
360                 gData.geofenceInterface->initialize();
361             }
362         }
363         if (NULL != gData.geofenceInterface) {
364             // either adds new Client or updates existing Client
365             gData.geofenceInterface->addClient(this, locationCallbacks);
366         }
367     }
368 
369     gData.clientData[this] = locationCallbacks;
370 
371     pthread_mutex_unlock(&gDataMutex);
372 }
373 
374 uint32_t
startTracking(TrackingOptions & trackingOptions)375 LocationAPI::startTracking(TrackingOptions& trackingOptions)
376 {
377     uint32_t id = 0;
378     pthread_mutex_lock(&gDataMutex);
379 
380     auto it = gData.clientData.find(this);
381     if (it != gData.clientData.end()) {
382         if (NULL != gData.gnssInterface) {
383             id = gData.gnssInterface->startTracking(this, trackingOptions);
384         } else {
385             LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
386                      __func__, __LINE__, this);
387         }
388     } else {
389         LOC_LOGE("%s:%d]: Location API client %p not found in client data",
390                  __func__, __LINE__, this);
391     }
392 
393     pthread_mutex_unlock(&gDataMutex);
394     return id;
395 }
396 
397 void
stopTracking(uint32_t id)398 LocationAPI::stopTracking(uint32_t id)
399 {
400     pthread_mutex_lock(&gDataMutex);
401 
402     auto it = gData.clientData.find(this);
403     if (it != gData.clientData.end()) {
404         if (gData.gnssInterface != NULL) {
405             gData.gnssInterface->stopTracking(this, id);
406         } else {
407             LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
408                      __func__, __LINE__, this);
409         }
410     } else {
411         LOC_LOGE("%s:%d]: Location API client %p not found in client data",
412                  __func__, __LINE__, this);
413     }
414 
415     pthread_mutex_unlock(&gDataMutex);
416 }
417 
418 void
updateTrackingOptions(uint32_t id,TrackingOptions & trackingOptions)419 LocationAPI::updateTrackingOptions(
420         uint32_t id, TrackingOptions& trackingOptions)
421 {
422     pthread_mutex_lock(&gDataMutex);
423 
424     auto it = gData.clientData.find(this);
425     if (it != gData.clientData.end()) {
426         if (gData.gnssInterface != NULL) {
427             gData.gnssInterface->updateTrackingOptions(this, id, trackingOptions);
428         } else {
429             LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
430                      __func__, __LINE__, this);
431         }
432     } else {
433         LOC_LOGE("%s:%d]: Location API client %p not found in client data",
434                  __func__, __LINE__, this);
435     }
436 
437     pthread_mutex_unlock(&gDataMutex);
438 }
439 
440 uint32_t
startBatching(BatchingOptions & batchingOptions)441 LocationAPI::startBatching(BatchingOptions &batchingOptions)
442 {
443     uint32_t id = 0;
444     pthread_mutex_lock(&gDataMutex);
445 
446     if (NULL != gData.batchingInterface) {
447         id = gData.batchingInterface->startBatching(this, batchingOptions);
448     } else {
449         LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
450                  __func__, __LINE__, this);
451     }
452 
453     pthread_mutex_unlock(&gDataMutex);
454     return id;
455 }
456 
457 void
stopBatching(uint32_t id)458 LocationAPI::stopBatching(uint32_t id)
459 {
460     pthread_mutex_lock(&gDataMutex);
461 
462     if (NULL != gData.batchingInterface) {
463         gData.batchingInterface->stopBatching(this, id);
464     } else {
465         LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
466                  __func__, __LINE__, this);
467     }
468 
469     pthread_mutex_unlock(&gDataMutex);
470 }
471 
472 void
updateBatchingOptions(uint32_t id,BatchingOptions & batchOptions)473 LocationAPI::updateBatchingOptions(uint32_t id, BatchingOptions& batchOptions)
474 {
475     pthread_mutex_lock(&gDataMutex);
476 
477     if (NULL != gData.batchingInterface) {
478         gData.batchingInterface->updateBatchingOptions(this, id, batchOptions);
479     } else {
480         LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
481                  __func__, __LINE__, this);
482     }
483 
484     pthread_mutex_unlock(&gDataMutex);
485 }
486 
487 void
getBatchedLocations(uint32_t id,size_t count)488 LocationAPI::getBatchedLocations(uint32_t id, size_t count)
489 {
490     pthread_mutex_lock(&gDataMutex);
491 
492     if (gData.batchingInterface != NULL) {
493         gData.batchingInterface->getBatchedLocations(this, id, count);
494     } else {
495         LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
496                  __func__, __LINE__, this);
497     }
498 
499     pthread_mutex_unlock(&gDataMutex);
500 }
501 
502 uint32_t*
addGeofences(size_t count,GeofenceOption * options,GeofenceInfo * info)503 LocationAPI::addGeofences(size_t count, GeofenceOption* options, GeofenceInfo* info)
504 {
505     uint32_t* ids = NULL;
506     pthread_mutex_lock(&gDataMutex);
507 
508     if (gData.geofenceInterface != NULL) {
509         ids = gData.geofenceInterface->addGeofences(this, count, options, info);
510     } else {
511         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
512                  __func__, __LINE__, this);
513     }
514 
515     pthread_mutex_unlock(&gDataMutex);
516     return ids;
517 }
518 
519 void
removeGeofences(size_t count,uint32_t * ids)520 LocationAPI::removeGeofences(size_t count, uint32_t* ids)
521 {
522     pthread_mutex_lock(&gDataMutex);
523 
524     if (gData.geofenceInterface != NULL) {
525         gData.geofenceInterface->removeGeofences(this, count, ids);
526     } else {
527         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
528                  __func__, __LINE__, this);
529     }
530 
531     pthread_mutex_unlock(&gDataMutex);
532 }
533 
534 void
modifyGeofences(size_t count,uint32_t * ids,GeofenceOption * options)535 LocationAPI::modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options)
536 {
537     pthread_mutex_lock(&gDataMutex);
538 
539     if (gData.geofenceInterface != NULL) {
540         gData.geofenceInterface->modifyGeofences(this, count, ids, options);
541     } else {
542         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
543                  __func__, __LINE__, this);
544     }
545 
546     pthread_mutex_unlock(&gDataMutex);
547 }
548 
549 void
pauseGeofences(size_t count,uint32_t * ids)550 LocationAPI::pauseGeofences(size_t count, uint32_t* ids)
551 {
552     pthread_mutex_lock(&gDataMutex);
553 
554     if (gData.geofenceInterface != NULL) {
555         gData.geofenceInterface->pauseGeofences(this, count, ids);
556     } else {
557         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
558                  __func__, __LINE__, this);
559     }
560 
561     pthread_mutex_unlock(&gDataMutex);
562 }
563 
564 void
resumeGeofences(size_t count,uint32_t * ids)565 LocationAPI::resumeGeofences(size_t count, uint32_t* ids)
566 {
567     pthread_mutex_lock(&gDataMutex);
568 
569     if (gData.geofenceInterface != NULL) {
570         gData.geofenceInterface->resumeGeofences(this, count, ids);
571     } else {
572         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
573                  __func__, __LINE__, this);
574     }
575 
576     pthread_mutex_unlock(&gDataMutex);
577 }
578 
579 void
gnssNiResponse(uint32_t id,GnssNiResponse response)580 LocationAPI::gnssNiResponse(uint32_t id, GnssNiResponse response)
581 {
582     pthread_mutex_lock(&gDataMutex);
583 
584     if (gData.gnssInterface != NULL) {
585         gData.gnssInterface->gnssNiResponse(this, id, response);
586     } else {
587         LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
588                  __func__, __LINE__, this);
589     }
590 
591     pthread_mutex_unlock(&gDataMutex);
592 }
593 
594 LocationControlAPI*
createInstance(LocationControlCallbacks & locationControlCallbacks)595 LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks)
596 {
597     LocationControlAPI* controlAPI = NULL;
598     pthread_mutex_lock(&gDataMutex);
599 
600     if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) {
601         if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
602             gData.gnssInterface =
603                 (GnssInterface*)loadLocationInterface<GnssInterface,
604                     getGnssInterface>("libgnss.so", "getGnssInterface");
605             if (NULL == gData.gnssInterface) {
606                 gGnssLoadFailed = true;
607                 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
608             } else {
609                 gData.gnssInterface->initialize();
610             }
611         }
612         if (NULL != gData.gnssInterface) {
613             gData.controlAPI = new LocationControlAPI();
614             gData.controlCallbacks = locationControlCallbacks;
615             gData.gnssInterface->setControlCallbacks(locationControlCallbacks);
616             controlAPI = gData.controlAPI;
617         }
618     }
619 
620     pthread_mutex_unlock(&gDataMutex);
621     return controlAPI;
622 }
623 
624 void
destroy()625 LocationControlAPI::destroy()
626 {
627     delete this;
628 }
629 
LocationControlAPI()630 LocationControlAPI::LocationControlAPI()
631 {
632     LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR");
633 }
634 
~LocationControlAPI()635 LocationControlAPI::~LocationControlAPI()
636 {
637     LOC_LOGD("LOCATION CONTROL API DESTRUCTOR");
638     pthread_mutex_lock(&gDataMutex);
639 
640     gData.controlAPI = NULL;
641 
642     pthread_mutex_unlock(&gDataMutex);
643 }
644 
645 uint32_t
enable(LocationTechnologyType techType)646 LocationControlAPI::enable(LocationTechnologyType techType)
647 {
648     uint32_t id = 0;
649     pthread_mutex_lock(&gDataMutex);
650 
651     if (gData.gnssInterface != NULL) {
652         id = gData.gnssInterface->enable(techType);
653     } else {
654         LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
655                  __func__, __LINE__, this);
656     }
657 
658     pthread_mutex_unlock(&gDataMutex);
659     return id;
660 }
661 
662 void
disable(uint32_t id)663 LocationControlAPI::disable(uint32_t id)
664 {
665     pthread_mutex_lock(&gDataMutex);
666 
667     if (gData.gnssInterface != NULL) {
668         gData.gnssInterface->disable(id);
669     } else {
670         LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
671                  __func__, __LINE__, this);
672     }
673 
674     pthread_mutex_unlock(&gDataMutex);
675 }
676 
677 uint32_t*
gnssUpdateConfig(GnssConfig config)678 LocationControlAPI::gnssUpdateConfig(GnssConfig config)
679 {
680     uint32_t* ids = NULL;
681     pthread_mutex_lock(&gDataMutex);
682 
683     if (gData.gnssInterface != NULL) {
684         ids = gData.gnssInterface->gnssUpdateConfig(config);
685     } else {
686         LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
687                  __func__, __LINE__, this);
688     }
689 
690     pthread_mutex_unlock(&gDataMutex);
691     return ids;
692 }
693 
gnssGetConfig(GnssConfigFlagsMask mask)694 uint32_t* LocationControlAPI::gnssGetConfig(GnssConfigFlagsMask mask) {
695 
696     uint32_t* ids = NULL;
697     pthread_mutex_lock(&gDataMutex);
698 
699     if (NULL != gData.gnssInterface) {
700         ids = gData.gnssInterface->gnssGetConfig(mask);
701     } else {
702         LOC_LOGe("No gnss interface available for Control API client %p", this);
703     }
704 
705     pthread_mutex_unlock(&gDataMutex);
706     return ids;
707 }
708 
709 uint32_t
gnssDeleteAidingData(GnssAidingData & data)710 LocationControlAPI::gnssDeleteAidingData(GnssAidingData& data)
711 {
712     uint32_t id = 0;
713     pthread_mutex_lock(&gDataMutex);
714 
715     if (gData.gnssInterface != NULL) {
716         id = gData.gnssInterface->gnssDeleteAidingData(data);
717     } else {
718         LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
719                  __func__, __LINE__, this);
720     }
721 
722     pthread_mutex_unlock(&gDataMutex);
723     return id;
724 }
725