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