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