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