1 /* Copyright (c) 2017-2020 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 
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 = (NULL != gData.gnssInterface);
237         bool removeFromBatchingInf = (NULL != gData.batchingInterface);
238         bool removeFromGeofenceInf = (NULL != gData.geofenceInterface);
239         bool needToWait = (removeFromGnssInf || removeFromBatchingInf || removeFromGeofenceInf);
240         LOC_LOGe("removeFromGnssInf: %d, removeFromBatchingInf: %d, removeFromGeofenceInf: %d,"
241                  "needToWait: %d", removeFromGnssInf, removeFromBatchingInf, removeFromGeofenceInf,
242                  needToWait);
243 
244         if ((NULL != destroyCompleteCb) && (true == needToWait)) {
245             LocationAPIDestroyCbData destroyCbData = {};
246             destroyCbData.destroyCompleteCb = destroyCompleteCb;
247             // record down from which adapter we need to wait for the destroy complete callback
248             // only when we have received all the needed callbacks from all the associated stacks,
249             // we shall notify the client.
250             destroyCbData.waitAdapterMask =
251                     (removeFromGnssInf ? LOCATION_ADAPTER_GNSS_TYPE_BIT : 0);
252             destroyCbData.waitAdapterMask |=
253                     (removeFromBatchingInf ? LOCATION_ADAPTER_BATCHING_TYPE_BIT : 0);
254             destroyCbData.waitAdapterMask |=
255                     (removeFromGeofenceInf ? LOCATION_ADAPTER_GEOFENCE_TYPE_BIT : 0);
256             gData.destroyClientData[this] = destroyCbData;
257             LOC_LOGi("destroy data stored in the map: 0x%x", destroyCbData.waitAdapterMask);
258         }
259 
260         if (removeFromGnssInf) {
261             gData.gnssInterface->removeClient(it->first,
262                                               onGnssRemoveClientCompleteCb);
263         }
264         if (removeFromBatchingInf) {
265             gData.batchingInterface->removeClient(it->first,
266                                              onBatchingRemoveClientCompleteCb);
267         }
268         if (removeFromGeofenceInf) {
269             gData.geofenceInterface->removeClient(it->first,
270                                                   onGeofenceRemoveClientCompleteCb);
271         }
272 
273         gData.clientData.erase(it);
274 
275         if ((NULL != destroyCompleteCb) && (false == needToWait)) {
276             invokeDestroyCb = true;
277         }
278     } else {
279         LOC_LOGE("%s:%d]: Location API client %p not found in client data",
280                  __func__, __LINE__, this);
281     }
282 
283     pthread_mutex_unlock(&gDataMutex);
284     if (invokeDestroyCb == true) {
285         (destroyCompleteCb) ();
286         delete this;
287     }
288 }
289 
LocationAPI()290 LocationAPI::LocationAPI()
291 {
292     LOC_LOGD("LOCATION API CONSTRUCTOR");
293 }
294 
295 // private destructor
~LocationAPI()296 LocationAPI::~LocationAPI()
297 {
298     LOC_LOGD("LOCATION API DESTRUCTOR");
299 }
300 
301 void
updateCallbacks(LocationCallbacks & locationCallbacks)302 LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks)
303 {
304     if (nullptr == locationCallbacks.capabilitiesCb ||
305         nullptr == locationCallbacks.responseCb ||
306         nullptr == locationCallbacks.collectiveResponseCb) {
307         return;
308     }
309 
310     pthread_mutex_lock(&gDataMutex);
311 
312     if (isGnssClient(locationCallbacks)) {
313         if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
314             gData.gnssInterface =
315                 (GnssInterface*)loadLocationInterface<GnssInterface,
316                     getGnssInterface>("libgnss.so", "getGnssInterface");
317             if (NULL == gData.gnssInterface) {
318                 gGnssLoadFailed = true;
319                 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
320             } else {
321                 gData.gnssInterface->initialize();
322             }
323         }
324         if (NULL != gData.gnssInterface) {
325             // either adds new Client or updates existing Client
326             gData.gnssInterface->addClient(this, locationCallbacks);
327         }
328     }
329 
330     if (isBatchingClient(locationCallbacks)) {
331         if (NULL == gData.batchingInterface && !gBatchingLoadFailed) {
332             gData.batchingInterface =
333                 (BatchingInterface*)loadLocationInterface<BatchingInterface,
334                  getBatchingInterface>("libbatching.so", "getBatchingInterface");
335             if (NULL == gData.batchingInterface) {
336                 gBatchingLoadFailed = true;
337                 LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__);
338             } else {
339                 gData.batchingInterface->initialize();
340             }
341         }
342         if (NULL != gData.batchingInterface) {
343             // either adds new Client or updates existing Client
344             gData.batchingInterface->addClient(this, locationCallbacks);
345         }
346     }
347 
348     if (isGeofenceClient(locationCallbacks)) {
349         if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
350             gData.geofenceInterface =
351                 (GeofenceInterface*)loadLocationInterface<GeofenceInterface,
352                  getGeofenceInterface>("libgeofencing.so", "getGeofenceInterface");
353             if (NULL == gData.geofenceInterface) {
354                 gGeofenceLoadFailed = true;
355                 LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
356             } else {
357                 gData.geofenceInterface->initialize();
358             }
359         }
360         if (NULL != gData.geofenceInterface) {
361             // either adds new Client or updates existing Client
362             gData.geofenceInterface->addClient(this, locationCallbacks);
363         }
364     }
365 
366     gData.clientData[this] = locationCallbacks;
367 
368     pthread_mutex_unlock(&gDataMutex);
369 }
370 
371 uint32_t
startTracking(TrackingOptions & trackingOptions)372 LocationAPI::startTracking(TrackingOptions& trackingOptions)
373 {
374     uint32_t id = 0;
375     pthread_mutex_lock(&gDataMutex);
376 
377     auto it = gData.clientData.find(this);
378     if (it != gData.clientData.end()) {
379         if (NULL != gData.gnssInterface) {
380             id = gData.gnssInterface->startTracking(this, trackingOptions);
381         } else {
382             LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
383                      __func__, __LINE__, this);
384         }
385     } else {
386         LOC_LOGE("%s:%d]: Location API client %p not found in client data",
387                  __func__, __LINE__, this);
388     }
389 
390     pthread_mutex_unlock(&gDataMutex);
391     return id;
392 }
393 
394 void
stopTracking(uint32_t id)395 LocationAPI::stopTracking(uint32_t id)
396 {
397     pthread_mutex_lock(&gDataMutex);
398 
399     auto it = gData.clientData.find(this);
400     if (it != gData.clientData.end()) {
401         if (gData.gnssInterface != NULL) {
402             gData.gnssInterface->stopTracking(this, id);
403         } else {
404             LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
405                      __func__, __LINE__, this);
406         }
407     } else {
408         LOC_LOGE("%s:%d]: Location API client %p not found in client data",
409                  __func__, __LINE__, this);
410     }
411 
412     pthread_mutex_unlock(&gDataMutex);
413 }
414 
415 void
updateTrackingOptions(uint32_t id,TrackingOptions & trackingOptions)416 LocationAPI::updateTrackingOptions(
417         uint32_t id, TrackingOptions& trackingOptions)
418 {
419     pthread_mutex_lock(&gDataMutex);
420 
421     auto it = gData.clientData.find(this);
422     if (it != gData.clientData.end()) {
423         if (gData.gnssInterface != NULL) {
424             gData.gnssInterface->updateTrackingOptions(this, id, trackingOptions);
425         } else {
426             LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
427                      __func__, __LINE__, this);
428         }
429     } else {
430         LOC_LOGE("%s:%d]: Location API client %p not found in client data",
431                  __func__, __LINE__, this);
432     }
433 
434     pthread_mutex_unlock(&gDataMutex);
435 }
436 
437 uint32_t
startBatching(BatchingOptions & batchingOptions)438 LocationAPI::startBatching(BatchingOptions &batchingOptions)
439 {
440     uint32_t id = 0;
441     pthread_mutex_lock(&gDataMutex);
442 
443     if (NULL != gData.batchingInterface) {
444         id = gData.batchingInterface->startBatching(this, batchingOptions);
445     } else {
446         LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
447                  __func__, __LINE__, this);
448     }
449 
450     pthread_mutex_unlock(&gDataMutex);
451     return id;
452 }
453 
454 void
stopBatching(uint32_t id)455 LocationAPI::stopBatching(uint32_t id)
456 {
457     pthread_mutex_lock(&gDataMutex);
458 
459     if (NULL != gData.batchingInterface) {
460         gData.batchingInterface->stopBatching(this, id);
461     } else {
462         LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
463                  __func__, __LINE__, this);
464     }
465 
466     pthread_mutex_unlock(&gDataMutex);
467 }
468 
469 void
updateBatchingOptions(uint32_t id,BatchingOptions & batchOptions)470 LocationAPI::updateBatchingOptions(uint32_t id, BatchingOptions& batchOptions)
471 {
472     pthread_mutex_lock(&gDataMutex);
473 
474     if (NULL != gData.batchingInterface) {
475         gData.batchingInterface->updateBatchingOptions(this, id, batchOptions);
476     } else {
477         LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
478                  __func__, __LINE__, this);
479     }
480 
481     pthread_mutex_unlock(&gDataMutex);
482 }
483 
484 void
getBatchedLocations(uint32_t id,size_t count)485 LocationAPI::getBatchedLocations(uint32_t id, size_t count)
486 {
487     pthread_mutex_lock(&gDataMutex);
488 
489     if (gData.batchingInterface != NULL) {
490         gData.batchingInterface->getBatchedLocations(this, id, count);
491     } else {
492         LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
493                  __func__, __LINE__, this);
494     }
495 
496     pthread_mutex_unlock(&gDataMutex);
497 }
498 
499 uint32_t*
addGeofences(size_t count,GeofenceOption * options,GeofenceInfo * info)500 LocationAPI::addGeofences(size_t count, GeofenceOption* options, GeofenceInfo* info)
501 {
502     uint32_t* ids = NULL;
503     pthread_mutex_lock(&gDataMutex);
504 
505     if (gData.geofenceInterface != NULL) {
506         ids = gData.geofenceInterface->addGeofences(this, count, options, info);
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     return ids;
514 }
515 
516 void
removeGeofences(size_t count,uint32_t * ids)517 LocationAPI::removeGeofences(size_t count, uint32_t* ids)
518 {
519     pthread_mutex_lock(&gDataMutex);
520 
521     if (gData.geofenceInterface != NULL) {
522         gData.geofenceInterface->removeGeofences(this, count, ids);
523     } else {
524         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
525                  __func__, __LINE__, this);
526     }
527 
528     pthread_mutex_unlock(&gDataMutex);
529 }
530 
531 void
modifyGeofences(size_t count,uint32_t * ids,GeofenceOption * options)532 LocationAPI::modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options)
533 {
534     pthread_mutex_lock(&gDataMutex);
535 
536     if (gData.geofenceInterface != NULL) {
537         gData.geofenceInterface->modifyGeofences(this, count, ids, options);
538     } else {
539         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
540                  __func__, __LINE__, this);
541     }
542 
543     pthread_mutex_unlock(&gDataMutex);
544 }
545 
546 void
pauseGeofences(size_t count,uint32_t * ids)547 LocationAPI::pauseGeofences(size_t count, uint32_t* ids)
548 {
549     pthread_mutex_lock(&gDataMutex);
550 
551     if (gData.geofenceInterface != NULL) {
552         gData.geofenceInterface->pauseGeofences(this, count, ids);
553     } else {
554         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
555                  __func__, __LINE__, this);
556     }
557 
558     pthread_mutex_unlock(&gDataMutex);
559 }
560 
561 void
resumeGeofences(size_t count,uint32_t * ids)562 LocationAPI::resumeGeofences(size_t count, uint32_t* ids)
563 {
564     pthread_mutex_lock(&gDataMutex);
565 
566     if (gData.geofenceInterface != NULL) {
567         gData.geofenceInterface->resumeGeofences(this, count, ids);
568     } else {
569         LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
570                  __func__, __LINE__, this);
571     }
572 
573     pthread_mutex_unlock(&gDataMutex);
574 }
575 
576 void
gnssNiResponse(uint32_t id,GnssNiResponse response)577 LocationAPI::gnssNiResponse(uint32_t id, GnssNiResponse response)
578 {
579     pthread_mutex_lock(&gDataMutex);
580 
581     if (gData.gnssInterface != NULL) {
582         gData.gnssInterface->gnssNiResponse(this, id, response);
583     } else {
584         LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
585                  __func__, __LINE__, this);
586     }
587 
588     pthread_mutex_unlock(&gDataMutex);
589 }
590 
591 LocationControlAPI*
createInstance(LocationControlCallbacks & locationControlCallbacks)592 LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks)
593 {
594     LocationControlAPI* controlAPI = NULL;
595     pthread_mutex_lock(&gDataMutex);
596 
597     if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) {
598         if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
599             gData.gnssInterface =
600                 (GnssInterface*)loadLocationInterface<GnssInterface,
601                     getGnssInterface>("libgnss.so", "getGnssInterface");
602             if (NULL == gData.gnssInterface) {
603                 gGnssLoadFailed = true;
604                 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
605             } else {
606                 gData.gnssInterface->initialize();
607             }
608         }
609         if (NULL != gData.gnssInterface) {
610             gData.controlAPI = new LocationControlAPI();
611             gData.controlCallbacks = locationControlCallbacks;
612             gData.gnssInterface->setControlCallbacks(locationControlCallbacks);
613             controlAPI = gData.controlAPI;
614         }
615     }
616 
617     pthread_mutex_unlock(&gDataMutex);
618     return controlAPI;
619 }
620 
621 void
destroy()622 LocationControlAPI::destroy()
623 {
624     delete this;
625 }
626 
LocationControlAPI()627 LocationControlAPI::LocationControlAPI()
628 {
629     LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR");
630 }
631 
~LocationControlAPI()632 LocationControlAPI::~LocationControlAPI()
633 {
634     LOC_LOGD("LOCATION CONTROL API DESTRUCTOR");
635     pthread_mutex_lock(&gDataMutex);
636 
637     gData.controlAPI = NULL;
638 
639     pthread_mutex_unlock(&gDataMutex);
640 }
641 
642 uint32_t
enable(LocationTechnologyType techType)643 LocationControlAPI::enable(LocationTechnologyType techType)
644 {
645     uint32_t id = 0;
646     pthread_mutex_lock(&gDataMutex);
647 
648     if (gData.gnssInterface != NULL) {
649         id = gData.gnssInterface->enable(techType);
650     } else {
651         LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
652                  __func__, __LINE__, this);
653     }
654 
655     pthread_mutex_unlock(&gDataMutex);
656     return id;
657 }
658 
659 void
disable(uint32_t id)660 LocationControlAPI::disable(uint32_t id)
661 {
662     pthread_mutex_lock(&gDataMutex);
663 
664     if (gData.gnssInterface != NULL) {
665         gData.gnssInterface->disable(id);
666     } else {
667         LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
668                  __func__, __LINE__, this);
669     }
670 
671     pthread_mutex_unlock(&gDataMutex);
672 }
673 
674 uint32_t*
gnssUpdateConfig(GnssConfig config)675 LocationControlAPI::gnssUpdateConfig(GnssConfig config)
676 {
677     uint32_t* ids = NULL;
678     pthread_mutex_lock(&gDataMutex);
679 
680     if (gData.gnssInterface != NULL) {
681         ids = gData.gnssInterface->gnssUpdateConfig(config);
682     } else {
683         LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
684                  __func__, __LINE__, this);
685     }
686 
687     pthread_mutex_unlock(&gDataMutex);
688     return ids;
689 }
690 
gnssGetConfig(GnssConfigFlagsMask mask)691 uint32_t* LocationControlAPI::gnssGetConfig(GnssConfigFlagsMask mask) {
692 
693     uint32_t* ids = NULL;
694     pthread_mutex_lock(&gDataMutex);
695 
696     if (NULL != gData.gnssInterface) {
697         ids = gData.gnssInterface->gnssGetConfig(mask);
698     } else {
699         LOC_LOGe("No gnss interface available for Control API client %p", this);
700     }
701 
702     pthread_mutex_unlock(&gDataMutex);
703     return ids;
704 }
705 
706 uint32_t
gnssDeleteAidingData(GnssAidingData & data)707 LocationControlAPI::gnssDeleteAidingData(GnssAidingData& data)
708 {
709     uint32_t id = 0;
710     pthread_mutex_lock(&gDataMutex);
711 
712     if (gData.gnssInterface != NULL) {
713         id = gData.gnssInterface->gnssDeleteAidingData(data);
714     } else {
715         LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
716                  __func__, __LINE__, this);
717     }
718 
719     pthread_mutex_unlock(&gDataMutex);
720     return id;
721 }
722 
resetConstellationConfig()723 uint32_t LocationControlAPI::resetConstellationConfig() {
724     uint32_t id = 0;
725     pthread_mutex_lock(&gDataMutex);
726 
727     if (gData.gnssInterface != NULL) {
728         id = gData.gnssInterface->gnssResetSvConfig();
729     } else {
730         LOC_LOGe("No gnss interface available for Location Control API");
731     }
732 
733     pthread_mutex_unlock(&gDataMutex);
734     return id;
735 }
736 
configConstellations(const GnssSvTypeConfig & svTypeConfig,const GnssSvIdConfig & svIdConfig)737 uint32_t LocationControlAPI::configConstellations(
738         const GnssSvTypeConfig& svTypeConfig,
739         const GnssSvIdConfig&   svIdConfig) {
740     uint32_t id = 0;
741     pthread_mutex_lock(&gDataMutex);
742 
743     if (gData.gnssInterface != NULL) {
744         id = gData.gnssInterface->gnssUpdateSvConfig(
745                 svTypeConfig, svIdConfig);
746     } else {
747         LOC_LOGe("No gnss interface available for Location Control API");
748     }
749 
750     pthread_mutex_unlock(&gDataMutex);
751     return id;
752 }
753 
configConstrainedTimeUncertainty(bool enable,float tuncThreshold,uint32_t energyBudget)754 uint32_t LocationControlAPI::configConstrainedTimeUncertainty(
755             bool enable, float tuncThreshold, uint32_t energyBudget) {
756     uint32_t id = 0;
757     pthread_mutex_lock(&gDataMutex);
758 
759     if (gData.gnssInterface != NULL) {
760         id = gData.gnssInterface->setConstrainedTunc(enable,
761                                                      tuncThreshold,
762                                                      energyBudget);
763     } else {
764         LOC_LOGe("No gnss interface available for Location Control API");
765     }
766 
767     pthread_mutex_unlock(&gDataMutex);
768     return id;
769 }
770 
configPositionAssistedClockEstimator(bool enable)771 uint32_t LocationControlAPI::configPositionAssistedClockEstimator(bool enable) {
772     uint32_t id = 0;
773     pthread_mutex_lock(&gDataMutex);
774 
775     if (gData.gnssInterface != NULL) {
776         id = gData.gnssInterface->setPositionAssistedClockEstimator(enable);
777     } else {
778         LOC_LOGe("No gnss interface available for Location Control API");
779     }
780 
781     pthread_mutex_unlock(&gDataMutex);
782     return id;
783 }
784 
configLeverArm(const LeverArmConfigInfo & configInfo)785 uint32_t LocationControlAPI::configLeverArm(const LeverArmConfigInfo& configInfo) {
786     uint32_t id = 0;
787     pthread_mutex_lock(&gDataMutex);
788 
789     if (gData.gnssInterface != NULL) {
790         id = gData.gnssInterface->configLeverArm(configInfo);
791     } else {
792         LOC_LOGe("No gnss interface available for Location Control API");
793     }
794 
795     pthread_mutex_unlock(&gDataMutex);
796     return id;
797 }
798