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