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