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