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