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