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 typedef void (createOSFramework)();
43 typedef void (destroyOSFramework)();
44
45 // GTP services
46 typedef uint32_t (setOptInStatusGetter)(bool userConsent, responseCallback* callback);
47 typedef void (enableProviderGetter)();
48 typedef void (disableProviderGetter)();
49 typedef void (getSingleNetworkLocationGetter)(trackingCallback* callback);
50 typedef void (stopNetworkLocationGetter)(trackingCallback* callback);
51
52 typedef struct {
53 // bit mask of the adpaters that we need to wait for the removeClientCompleteCallback
54 // before we invoke the registered locationApiDestroyCompleteCallback
55 LocationAdapterTypeMask waitAdapterMask;
56 locationApiDestroyCompleteCallback destroyCompleteCb;
57 } LocationAPIDestroyCbData;
58
59 // This is the map for the client that has requested destroy with
60 // destroy callback provided.
61 typedef std::map<LocationAPI*, LocationAPIDestroyCbData>
62 LocationClientDestroyCbMap;
63
64 typedef std::map<LocationAPI*, LocationCallbacks> LocationClientMap;
65 typedef struct {
66 LocationClientMap clientData;
67 LocationClientDestroyCbMap destroyClientData;
68 LocationControlAPI* controlAPI;
69 LocationControlCallbacks controlCallbacks;
70 GnssInterface* gnssInterface;
71 GeofenceInterface* geofenceInterface;
72 BatchingInterface* batchingInterface;
73 } LocationAPIData;
74
75 static LocationAPIData gData = {};
76 static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER;
77 static bool gGnssLoadFailed = false;
78 static bool gBatchingLoadFailed = false;
79 static bool gGeofenceLoadFailed = false;
80 static uint32_t gOSFrameworkRefCount = 0;
81
82 template <typename T1, typename T2>
loadLocationInterface(const char * library,const char * name)83 static const T1* loadLocationInterface(const char* library, const char* name) {
84 void* libhandle = nullptr;
85 T2* getter = (T2*)dlGetSymFromLib(libhandle, library, name);
86 if (nullptr == getter) {
87 return (const T1*) getter;
88 }else {
89 return (*getter)();
90 }
91 }
92
createOSFrameworkInstance()93 static void createOSFrameworkInstance() {
94 void* libHandle = nullptr;
95 createOSFramework* getter = (createOSFramework*)dlGetSymFromLib(libHandle,
96 "liblocationservice_glue.so", "createOSFramework");
97 if (getter != nullptr) {
98 (*getter)();
99 } else {
100 LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
101 }
102 }
103
destroyOSFrameworkInstance()104 static void destroyOSFrameworkInstance() {
105 void* libHandle = nullptr;
106 destroyOSFramework* getter = (destroyOSFramework*)dlGetSymFromLib(libHandle,
107 "liblocationservice_glue.so", "destroyOSFramework");
108 if (getter != nullptr) {
109 (*getter)();
110 } else {
111 LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
112 }
113 }
114
needsGnssTrackingInfo(LocationCallbacks & locationCallbacks)115 static bool needsGnssTrackingInfo(LocationCallbacks& locationCallbacks)
116 {
117 return (locationCallbacks.gnssLocationInfoCb != nullptr ||
118 locationCallbacks.engineLocationsInfoCb != nullptr ||
119 locationCallbacks.gnssSvCb != nullptr ||
120 locationCallbacks.gnssNmeaCb != nullptr ||
121 locationCallbacks.gnssDataCb != nullptr ||
122 locationCallbacks.gnssMeasurementsCb != nullptr);
123 }
124
isGnssClient(LocationCallbacks & locationCallbacks)125 static bool isGnssClient(LocationCallbacks& locationCallbacks)
126 {
127 return (locationCallbacks.gnssNiCb != nullptr ||
128 locationCallbacks.trackingCb != nullptr ||
129 locationCallbacks.gnssLocationInfoCb != nullptr ||
130 locationCallbacks.engineLocationsInfoCb != nullptr ||
131 locationCallbacks.gnssSvCb != nullptr ||
132 locationCallbacks.gnssNmeaCb != nullptr ||
133 locationCallbacks.gnssDataCb != nullptr ||
134 locationCallbacks.gnssMeasurementsCb != nullptr ||
135 locationCallbacks.locationSystemInfoCb != nullptr);
136 }
137
isBatchingClient(LocationCallbacks & locationCallbacks)138 static bool isBatchingClient(LocationCallbacks& locationCallbacks)
139 {
140 return (locationCallbacks.batchingCb != nullptr);
141 }
142
isGeofenceClient(LocationCallbacks & locationCallbacks)143 static bool isGeofenceClient(LocationCallbacks& locationCallbacks)
144 {
145 return (locationCallbacks.geofenceBreachCb != nullptr ||
146 locationCallbacks.geofenceStatusCb != nullptr);
147 }
148
149
onRemoveClientCompleteCb(LocationAdapterTypeMask adapterType)150 void LocationAPI::onRemoveClientCompleteCb (LocationAdapterTypeMask adapterType)
151 {
152 bool invokeCallback = false;
153 locationApiDestroyCompleteCallback destroyCompleteCb;
154 LOC_LOGd("adatper type %x", adapterType);
155 pthread_mutex_lock(&gDataMutex);
156 auto it = gData.destroyClientData.find(this);
157 if (it != gData.destroyClientData.end()) {
158 it->second.waitAdapterMask &= ~adapterType;
159 if (it->second.waitAdapterMask == 0) {
160 invokeCallback = true;
161 destroyCompleteCb = it->second.destroyCompleteCb;
162 gData.destroyClientData.erase(it);
163 }
164 }
165 pthread_mutex_unlock(&gDataMutex);
166
167 if (invokeCallback) {
168 LOC_LOGd("invoke client destroy cb");
169 if (!destroyCompleteCb) {
170 (destroyCompleteCb) ();
171 }
172
173 delete this;
174 }
175 }
176
onGnssRemoveClientCompleteCb(LocationAPI * client)177 void onGnssRemoveClientCompleteCb (LocationAPI* client)
178 {
179 client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GNSS_TYPE_BIT);
180 }
181
onBatchingRemoveClientCompleteCb(LocationAPI * client)182 void onBatchingRemoveClientCompleteCb (LocationAPI* client)
183 {
184 client->onRemoveClientCompleteCb (LOCATION_ADAPTER_BATCHING_TYPE_BIT);
185 }
186
onGeofenceRemoveClientCompleteCb(LocationAPI * client)187 void onGeofenceRemoveClientCompleteCb (LocationAPI* client)
188 {
189 client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GEOFENCE_TYPE_BIT);
190 }
191
192 LocationAPI*
createInstance(LocationCallbacks & locationCallbacks)193 LocationAPI::createInstance (LocationCallbacks& locationCallbacks)
194 {
195 if (nullptr == locationCallbacks.capabilitiesCb ||
196 nullptr == locationCallbacks.responseCb ||
197 nullptr == locationCallbacks.collectiveResponseCb) {
198 LOC_LOGe("missing mandatory callback, return null");
199 return NULL;
200 }
201
202 LocationAPI* newLocationAPI = new LocationAPI();
203 bool requestedCapabilities = false;
204
205 pthread_mutex_lock(&gDataMutex);
206
207 gOSFrameworkRefCount++;
208 if (1 == gOSFrameworkRefCount) {
209 createOSFrameworkInstance();
210 }
211
212 if (isGnssClient(locationCallbacks)) {
213 if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
214 gData.gnssInterface =
215 (GnssInterface*)loadLocationInterface<GnssInterface,
216 getGnssInterface>("libgnss.so", "getGnssInterface");
217 if (NULL == gData.gnssInterface) {
218 gGnssLoadFailed = true;
219 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
220 } else {
221 gData.gnssInterface->initialize();
222 }
223 }
224 if (NULL != gData.gnssInterface) {
225 gData.gnssInterface->addClient(newLocationAPI, locationCallbacks);
226 if (!requestedCapabilities) {
227 gData.gnssInterface->requestCapabilities(newLocationAPI);
228 requestedCapabilities = true;
229 }
230 }
231 }
232
233 if (isBatchingClient(locationCallbacks)) {
234 if (NULL == gData.batchingInterface && !gBatchingLoadFailed) {
235 gData.batchingInterface =
236 (BatchingInterface*)loadLocationInterface<BatchingInterface,
237 getBatchingInterface>("libbatching.so", "getBatchingInterface");
238 if (NULL == gData.batchingInterface) {
239 gBatchingLoadFailed = true;
240 LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__);
241 } else {
242 gData.batchingInterface->initialize();
243 }
244 }
245 if (NULL != gData.batchingInterface) {
246 gData.batchingInterface->addClient(newLocationAPI, locationCallbacks);
247 if (!requestedCapabilities) {
248 gData.batchingInterface->requestCapabilities(newLocationAPI);
249 requestedCapabilities = true;
250 }
251 }
252 }
253
254 if (isGeofenceClient(locationCallbacks)) {
255 if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
256 gData.geofenceInterface =
257 (GeofenceInterface*)loadLocationInterface<GeofenceInterface,
258 getGeofenceInterface>("libgeofencing.so", "getGeofenceInterface");
259 if (NULL == gData.geofenceInterface) {
260 gGeofenceLoadFailed = true;
261 LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
262 } else {
263 gData.geofenceInterface->initialize();
264 }
265 }
266 if (NULL != gData.geofenceInterface) {
267 gData.geofenceInterface->addClient(newLocationAPI, locationCallbacks);
268 if (!requestedCapabilities) {
269 gData.geofenceInterface->requestCapabilities(newLocationAPI);
270 requestedCapabilities = true;
271 }
272 }
273 }
274
275 gData.clientData[newLocationAPI] = locationCallbacks;
276
277 pthread_mutex_unlock(&gDataMutex);
278
279 return newLocationAPI;
280 }
281
282 void
destroy(locationApiDestroyCompleteCallback destroyCompleteCb)283 LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb)
284 {
285 bool invokeDestroyCb = false;
286
287 pthread_mutex_lock(&gDataMutex);
288 auto it = gData.clientData.find(this);
289 if (it != gData.clientData.end()) {
290 bool removeFromGnssInf = (NULL != gData.gnssInterface);
291 bool removeFromBatchingInf = (NULL != gData.batchingInterface);
292 bool removeFromGeofenceInf = (NULL != gData.geofenceInterface);
293 bool needToWait = (removeFromGnssInf || removeFromBatchingInf || removeFromGeofenceInf);
294 LOC_LOGe("removeFromGnssInf: %d, removeFromBatchingInf: %d, removeFromGeofenceInf: %d,"
295 "needToWait: %d", removeFromGnssInf, removeFromBatchingInf, removeFromGeofenceInf,
296 needToWait);
297
298 if ((NULL != destroyCompleteCb) && (true == needToWait)) {
299 LocationAPIDestroyCbData destroyCbData = {};
300 destroyCbData.destroyCompleteCb = destroyCompleteCb;
301 // record down from which adapter we need to wait for the destroy complete callback
302 // only when we have received all the needed callbacks from all the associated stacks,
303 // we shall notify the client.
304 destroyCbData.waitAdapterMask =
305 (removeFromGnssInf ? LOCATION_ADAPTER_GNSS_TYPE_BIT : 0);
306 destroyCbData.waitAdapterMask |=
307 (removeFromBatchingInf ? LOCATION_ADAPTER_BATCHING_TYPE_BIT : 0);
308 destroyCbData.waitAdapterMask |=
309 (removeFromGeofenceInf ? LOCATION_ADAPTER_GEOFENCE_TYPE_BIT : 0);
310 gData.destroyClientData[this] = destroyCbData;
311 LOC_LOGi("destroy data stored in the map: 0x%x", destroyCbData.waitAdapterMask);
312 }
313
314 if (removeFromGnssInf) {
315 gData.gnssInterface->removeClient(it->first,
316 onGnssRemoveClientCompleteCb);
317 }
318 if (removeFromBatchingInf) {
319 gData.batchingInterface->removeClient(it->first,
320 onBatchingRemoveClientCompleteCb);
321 }
322 if (removeFromGeofenceInf) {
323 gData.geofenceInterface->removeClient(it->first,
324 onGeofenceRemoveClientCompleteCb);
325 }
326
327 gData.clientData.erase(it);
328
329 if (!needToWait) {
330 invokeDestroyCb = true;
331 }
332 } else {
333 LOC_LOGE("%s:%d]: Location API client %p not found in client data",
334 __func__, __LINE__, this);
335 }
336
337 if (1 == gOSFrameworkRefCount) {
338 destroyOSFrameworkInstance();
339 }
340 gOSFrameworkRefCount--;
341
342 pthread_mutex_unlock(&gDataMutex);
343 if (invokeDestroyCb) {
344 if (!destroyCompleteCb) {
345 (destroyCompleteCb) ();
346 }
347 delete this;
348 }
349 }
350
LocationAPI()351 LocationAPI::LocationAPI()
352 {
353 LOC_LOGD("LOCATION API CONSTRUCTOR");
354 }
355
356 // private destructor
~LocationAPI()357 LocationAPI::~LocationAPI()
358 {
359 LOC_LOGD("LOCATION API DESTRUCTOR");
360 }
361
362 void
updateCallbacks(LocationCallbacks & locationCallbacks)363 LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks)
364 {
365 if (nullptr == locationCallbacks.capabilitiesCb ||
366 nullptr == locationCallbacks.responseCb ||
367 nullptr == locationCallbacks.collectiveResponseCb) {
368 return;
369 }
370
371 pthread_mutex_lock(&gDataMutex);
372
373 if (isGnssClient(locationCallbacks)) {
374 if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
375 gData.gnssInterface =
376 (GnssInterface*)loadLocationInterface<GnssInterface,
377 getGnssInterface>("libgnss.so", "getGnssInterface");
378 if (NULL == gData.gnssInterface) {
379 gGnssLoadFailed = true;
380 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
381 } else {
382 gData.gnssInterface->initialize();
383 }
384 }
385 if (NULL != gData.gnssInterface) {
386 // either adds new Client or updates existing Client
387 gData.gnssInterface->addClient(this, locationCallbacks);
388 }
389 }
390
391 if (isBatchingClient(locationCallbacks)) {
392 if (NULL == gData.batchingInterface && !gBatchingLoadFailed) {
393 gData.batchingInterface =
394 (BatchingInterface*)loadLocationInterface<BatchingInterface,
395 getBatchingInterface>("libbatching.so", "getBatchingInterface");
396 if (NULL == gData.batchingInterface) {
397 gBatchingLoadFailed = true;
398 LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__);
399 } else {
400 gData.batchingInterface->initialize();
401 }
402 }
403 if (NULL != gData.batchingInterface) {
404 // either adds new Client or updates existing Client
405 gData.batchingInterface->addClient(this, locationCallbacks);
406 }
407 }
408
409 if (isGeofenceClient(locationCallbacks)) {
410 if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
411 gData.geofenceInterface =
412 (GeofenceInterface*)loadLocationInterface<GeofenceInterface,
413 getGeofenceInterface>("libgeofencing.so", "getGeofenceInterface");
414 if (NULL == gData.geofenceInterface) {
415 gGeofenceLoadFailed = true;
416 LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
417 } else {
418 gData.geofenceInterface->initialize();
419 }
420 }
421 if (NULL != gData.geofenceInterface) {
422 // either adds new Client or updates existing Client
423 gData.geofenceInterface->addClient(this, locationCallbacks);
424 }
425 }
426
427 gData.clientData[this] = locationCallbacks;
428
429 pthread_mutex_unlock(&gDataMutex);
430 }
431
432 uint32_t
startTracking(TrackingOptions & trackingOptions)433 LocationAPI::startTracking(TrackingOptions& trackingOptions)
434 {
435 uint32_t id = 0;
436 pthread_mutex_lock(&gDataMutex);
437
438 auto it = gData.clientData.find(this);
439 if (it != gData.clientData.end()) {
440 if (NULL != gData.gnssInterface) {
441 id = gData.gnssInterface->startTracking(this, trackingOptions);
442 } else {
443 LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
444 __func__, __LINE__, this);
445 }
446 } else {
447 LOC_LOGE("%s:%d]: Location API client %p not found in client data",
448 __func__, __LINE__, this);
449 }
450
451 pthread_mutex_unlock(&gDataMutex);
452 return id;
453 }
454
455 void
stopTracking(uint32_t id)456 LocationAPI::stopTracking(uint32_t id)
457 {
458 pthread_mutex_lock(&gDataMutex);
459
460 auto it = gData.clientData.find(this);
461 if (it != gData.clientData.end()) {
462 if (gData.gnssInterface != NULL) {
463 gData.gnssInterface->stopTracking(this, id);
464 } else {
465 LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
466 __func__, __LINE__, this);
467 }
468 } else {
469 LOC_LOGE("%s:%d]: Location API client %p not found in client data",
470 __func__, __LINE__, this);
471 }
472
473 pthread_mutex_unlock(&gDataMutex);
474 }
475
476 void
updateTrackingOptions(uint32_t id,TrackingOptions & trackingOptions)477 LocationAPI::updateTrackingOptions(
478 uint32_t id, TrackingOptions& trackingOptions)
479 {
480 pthread_mutex_lock(&gDataMutex);
481
482 auto it = gData.clientData.find(this);
483 if (it != gData.clientData.end()) {
484 if (gData.gnssInterface != NULL) {
485 gData.gnssInterface->updateTrackingOptions(this, id, trackingOptions);
486 } else {
487 LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
488 __func__, __LINE__, this);
489 }
490 } else {
491 LOC_LOGE("%s:%d]: Location API client %p not found in client data",
492 __func__, __LINE__, this);
493 }
494
495 pthread_mutex_unlock(&gDataMutex);
496 }
497
498 uint32_t
startBatching(BatchingOptions & batchingOptions)499 LocationAPI::startBatching(BatchingOptions &batchingOptions)
500 {
501 uint32_t id = 0;
502 pthread_mutex_lock(&gDataMutex);
503
504 if (NULL != gData.batchingInterface) {
505 id = gData.batchingInterface->startBatching(this, batchingOptions);
506 } else {
507 LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
508 __func__, __LINE__, this);
509 }
510
511 pthread_mutex_unlock(&gDataMutex);
512 return id;
513 }
514
515 void
stopBatching(uint32_t id)516 LocationAPI::stopBatching(uint32_t id)
517 {
518 pthread_mutex_lock(&gDataMutex);
519
520 if (NULL != gData.batchingInterface) {
521 gData.batchingInterface->stopBatching(this, id);
522 } else {
523 LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
524 __func__, __LINE__, this);
525 }
526
527 pthread_mutex_unlock(&gDataMutex);
528 }
529
530 void
updateBatchingOptions(uint32_t id,BatchingOptions & batchOptions)531 LocationAPI::updateBatchingOptions(uint32_t id, BatchingOptions& batchOptions)
532 {
533 pthread_mutex_lock(&gDataMutex);
534
535 if (NULL != gData.batchingInterface) {
536 gData.batchingInterface->updateBatchingOptions(this, id, batchOptions);
537 } else {
538 LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
539 __func__, __LINE__, this);
540 }
541
542 pthread_mutex_unlock(&gDataMutex);
543 }
544
545 void
getBatchedLocations(uint32_t id,size_t count)546 LocationAPI::getBatchedLocations(uint32_t id, size_t count)
547 {
548 pthread_mutex_lock(&gDataMutex);
549
550 if (gData.batchingInterface != NULL) {
551 gData.batchingInterface->getBatchedLocations(this, id, count);
552 } else {
553 LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
554 __func__, __LINE__, this);
555 }
556
557 pthread_mutex_unlock(&gDataMutex);
558 }
559
560 uint32_t*
addGeofences(size_t count,GeofenceOption * options,GeofenceInfo * info)561 LocationAPI::addGeofences(size_t count, GeofenceOption* options, GeofenceInfo* info)
562 {
563 uint32_t* ids = NULL;
564 pthread_mutex_lock(&gDataMutex);
565
566 if (gData.geofenceInterface != NULL) {
567 ids = gData.geofenceInterface->addGeofences(this, count, options, info);
568 } else {
569 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
570 __func__, __LINE__, this);
571 }
572
573 pthread_mutex_unlock(&gDataMutex);
574 return ids;
575 }
576
577 void
removeGeofences(size_t count,uint32_t * ids)578 LocationAPI::removeGeofences(size_t count, uint32_t* ids)
579 {
580 pthread_mutex_lock(&gDataMutex);
581
582 if (gData.geofenceInterface != NULL) {
583 gData.geofenceInterface->removeGeofences(this, count, ids);
584 } else {
585 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
586 __func__, __LINE__, this);
587 }
588
589 pthread_mutex_unlock(&gDataMutex);
590 }
591
592 void
modifyGeofences(size_t count,uint32_t * ids,GeofenceOption * options)593 LocationAPI::modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options)
594 {
595 pthread_mutex_lock(&gDataMutex);
596
597 if (gData.geofenceInterface != NULL) {
598 gData.geofenceInterface->modifyGeofences(this, count, ids, options);
599 } else {
600 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
601 __func__, __LINE__, this);
602 }
603
604 pthread_mutex_unlock(&gDataMutex);
605 }
606
607 void
pauseGeofences(size_t count,uint32_t * ids)608 LocationAPI::pauseGeofences(size_t count, uint32_t* ids)
609 {
610 pthread_mutex_lock(&gDataMutex);
611
612 if (gData.geofenceInterface != NULL) {
613 gData.geofenceInterface->pauseGeofences(this, count, ids);
614 } else {
615 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
616 __func__, __LINE__, this);
617 }
618
619 pthread_mutex_unlock(&gDataMutex);
620 }
621
622 void
resumeGeofences(size_t count,uint32_t * ids)623 LocationAPI::resumeGeofences(size_t count, uint32_t* ids)
624 {
625 pthread_mutex_lock(&gDataMutex);
626
627 if (gData.geofenceInterface != NULL) {
628 gData.geofenceInterface->resumeGeofences(this, count, ids);
629 } else {
630 LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
631 __func__, __LINE__, this);
632 }
633
634 pthread_mutex_unlock(&gDataMutex);
635 }
636
637 void
gnssNiResponse(uint32_t id,GnssNiResponse response)638 LocationAPI::gnssNiResponse(uint32_t id, GnssNiResponse response)
639 {
640 pthread_mutex_lock(&gDataMutex);
641
642 if (gData.gnssInterface != NULL) {
643 gData.gnssInterface->gnssNiResponse(this, id, response);
644 } else {
645 LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
646 __func__, __LINE__, this);
647 }
648
649 pthread_mutex_unlock(&gDataMutex);
650 }
651
enableNetworkProvider()652 void LocationAPI::enableNetworkProvider() {
653 void* libHandle = nullptr;
654 enableProviderGetter* setter = (enableProviderGetter*)dlGetSymFromLib(libHandle,
655 "liblocationservice_glue.so", "enableNetworkProvider");
656 if (setter != nullptr) {
657 (*setter)();
658 } else {
659 LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
660 }
661 }
662
disableNetworkProvider()663 void LocationAPI::disableNetworkProvider() {
664 void* libHandle = nullptr;
665 disableProviderGetter* setter = (disableProviderGetter*)dlGetSymFromLib(libHandle,
666 "liblocationservice_glue.so", "disableNetworkProvider");
667 if (setter != nullptr) {
668 (*setter)();
669 } else {
670 LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
671 }
672 }
673
startNetworkLocation(trackingCallback * callback)674 void LocationAPI::startNetworkLocation(trackingCallback* callback) {
675 void* libHandle = nullptr;
676 getSingleNetworkLocationGetter* setter =
677 (getSingleNetworkLocationGetter*)dlGetSymFromLib(libHandle,
678 "liblocationservice_glue.so", "startNetworkLocation");
679 if (setter != nullptr) {
680 (*setter)(callback);
681 } else {
682 LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
683 }
684 }
685
stopNetworkLocation(trackingCallback * callback)686 void LocationAPI::stopNetworkLocation(trackingCallback* callback) {
687 void* libHandle = nullptr;
688 stopNetworkLocationGetter* setter = (stopNetworkLocationGetter*)dlGetSymFromLib(libHandle,
689 "liblocationservice_glue.so", "stopNetworkLocation");
690 if (setter != nullptr) {
691 LOC_LOGe("called");
692 (*setter)(callback);
693 } else {
694 LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
695 }
696 }
697
698 LocationControlAPI*
createInstance(LocationControlCallbacks & locationControlCallbacks)699 LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks)
700 {
701 LocationControlAPI* controlAPI = NULL;
702 pthread_mutex_lock(&gDataMutex);
703
704 if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) {
705 if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
706 gData.gnssInterface =
707 (GnssInterface*)loadLocationInterface<GnssInterface,
708 getGnssInterface>("libgnss.so", "getGnssInterface");
709 if (NULL == gData.gnssInterface) {
710 gGnssLoadFailed = true;
711 LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
712 } else {
713 gData.gnssInterface->initialize();
714 }
715 }
716 if (NULL != gData.gnssInterface) {
717 gData.controlAPI = new LocationControlAPI();
718 gData.controlCallbacks = locationControlCallbacks;
719 gData.gnssInterface->setControlCallbacks(locationControlCallbacks);
720 controlAPI = gData.controlAPI;
721 }
722 }
723
724 pthread_mutex_unlock(&gDataMutex);
725 return controlAPI;
726 }
727
728 void
destroy()729 LocationControlAPI::destroy()
730 {
731 delete this;
732 }
733
LocationControlAPI()734 LocationControlAPI::LocationControlAPI()
735 {
736 LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR");
737 }
738
~LocationControlAPI()739 LocationControlAPI::~LocationControlAPI()
740 {
741 LOC_LOGD("LOCATION CONTROL API DESTRUCTOR");
742 pthread_mutex_lock(&gDataMutex);
743
744 gData.controlAPI = NULL;
745
746 pthread_mutex_unlock(&gDataMutex);
747 }
748
749 uint32_t
enable(LocationTechnologyType techType)750 LocationControlAPI::enable(LocationTechnologyType techType)
751 {
752 uint32_t id = 0;
753 pthread_mutex_lock(&gDataMutex);
754
755 if (gData.gnssInterface != NULL) {
756 id = gData.gnssInterface->enable(techType);
757 } else {
758 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
759 __func__, __LINE__, this);
760 }
761
762 pthread_mutex_unlock(&gDataMutex);
763 return id;
764 }
765
766 void
disable(uint32_t id)767 LocationControlAPI::disable(uint32_t id)
768 {
769 pthread_mutex_lock(&gDataMutex);
770
771 if (gData.gnssInterface != NULL) {
772 gData.gnssInterface->disable(id);
773 } else {
774 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
775 __func__, __LINE__, this);
776 }
777
778 pthread_mutex_unlock(&gDataMutex);
779 }
780
781 uint32_t*
gnssUpdateConfig(const GnssConfig & config)782 LocationControlAPI::gnssUpdateConfig(const GnssConfig& config)
783 {
784 uint32_t* ids = NULL;
785 pthread_mutex_lock(&gDataMutex);
786
787 if (gData.gnssInterface != NULL) {
788 ids = gData.gnssInterface->gnssUpdateConfig(config);
789 } else {
790 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
791 __func__, __LINE__, this);
792 }
793
794 pthread_mutex_unlock(&gDataMutex);
795 return ids;
796 }
797
gnssGetConfig(GnssConfigFlagsMask mask)798 uint32_t* LocationControlAPI::gnssGetConfig(GnssConfigFlagsMask mask) {
799
800 uint32_t* ids = NULL;
801 pthread_mutex_lock(&gDataMutex);
802
803 if (NULL != gData.gnssInterface) {
804 ids = gData.gnssInterface->gnssGetConfig(mask);
805 } else {
806 LOC_LOGe("No gnss interface available for Control API client %p", this);
807 }
808
809 pthread_mutex_unlock(&gDataMutex);
810 return ids;
811 }
812
813 uint32_t
gnssDeleteAidingData(GnssAidingData & data)814 LocationControlAPI::gnssDeleteAidingData(GnssAidingData& data)
815 {
816 uint32_t id = 0;
817 pthread_mutex_lock(&gDataMutex);
818
819 if (gData.gnssInterface != NULL) {
820 id = gData.gnssInterface->gnssDeleteAidingData(data);
821 } else {
822 LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
823 __func__, __LINE__, this);
824 }
825
826 pthread_mutex_unlock(&gDataMutex);
827 return id;
828 }
829
configConstellations(const GnssSvTypeConfig & constellationEnablementConfig,const GnssSvIdConfig & blacklistSvConfig)830 uint32_t LocationControlAPI::configConstellations(
831 const GnssSvTypeConfig& constellationEnablementConfig,
832 const GnssSvIdConfig& blacklistSvConfig) {
833 uint32_t id = 0;
834 pthread_mutex_lock(&gDataMutex);
835
836 if (gData.gnssInterface != NULL) {
837 id = gData.gnssInterface->gnssUpdateSvConfig(
838 constellationEnablementConfig, blacklistSvConfig);
839 } else {
840 LOC_LOGe("No gnss interface available for Location Control API");
841 }
842
843 pthread_mutex_unlock(&gDataMutex);
844 return id;
845 }
846
configConstellationSecondaryBand(const GnssSvTypeConfig & secondaryBandConfig)847 uint32_t LocationControlAPI::configConstellationSecondaryBand(
848 const GnssSvTypeConfig& secondaryBandConfig) {
849 uint32_t id = 0;
850 pthread_mutex_lock(&gDataMutex);
851
852 if (gData.gnssInterface != NULL) {
853 id = gData.gnssInterface->gnssUpdateSecondaryBandConfig(secondaryBandConfig);
854 } else {
855 LOC_LOGe("No gnss interface available for Location Control API");
856 }
857
858 pthread_mutex_unlock(&gDataMutex);
859 return id;
860 }
861
configConstrainedTimeUncertainty(bool enable,float tuncThreshold,uint32_t energyBudget)862 uint32_t LocationControlAPI::configConstrainedTimeUncertainty(
863 bool enable, float tuncThreshold, uint32_t energyBudget) {
864 uint32_t id = 0;
865 pthread_mutex_lock(&gDataMutex);
866
867 if (gData.gnssInterface != NULL) {
868 id = gData.gnssInterface->setConstrainedTunc(enable,
869 tuncThreshold,
870 energyBudget);
871 } else {
872 LOC_LOGe("No gnss interface available for Location Control API");
873 }
874
875 pthread_mutex_unlock(&gDataMutex);
876 return id;
877 }
878
configPositionAssistedClockEstimator(bool enable)879 uint32_t LocationControlAPI::configPositionAssistedClockEstimator(bool enable) {
880 uint32_t id = 0;
881 pthread_mutex_lock(&gDataMutex);
882
883 if (gData.gnssInterface != NULL) {
884 id = gData.gnssInterface->setPositionAssistedClockEstimator(enable);
885 } else {
886 LOC_LOGe("No gnss interface available for Location Control API");
887 }
888
889 pthread_mutex_unlock(&gDataMutex);
890 return id;
891 }
892
configLeverArm(const LeverArmConfigInfo & configInfo)893 uint32_t LocationControlAPI::configLeverArm(const LeverArmConfigInfo& configInfo) {
894 uint32_t id = 0;
895 pthread_mutex_lock(&gDataMutex);
896
897 if (gData.gnssInterface != NULL) {
898 id = gData.gnssInterface->configLeverArm(configInfo);
899 } else {
900 LOC_LOGe("No gnss interface available for Location Control API");
901 }
902
903 pthread_mutex_unlock(&gDataMutex);
904 return id;
905 }
906
configRobustLocation(bool enable,bool enableForE911)907 uint32_t LocationControlAPI::configRobustLocation(bool enable, bool enableForE911) {
908 uint32_t id = 0;
909 pthread_mutex_lock(&gDataMutex);
910
911 if (gData.gnssInterface != NULL) {
912 id = gData.gnssInterface->configRobustLocation(enable, enableForE911);
913 } else {
914 LOC_LOGe("No gnss interface available for Location Control API");
915 }
916
917 pthread_mutex_unlock(&gDataMutex);
918 return id;
919 }
920
configMinGpsWeek(uint16_t minGpsWeek)921 uint32_t LocationControlAPI::configMinGpsWeek(uint16_t minGpsWeek) {
922 uint32_t id = 0;
923 pthread_mutex_lock(&gDataMutex);
924
925 if (gData.gnssInterface != NULL) {
926 id = gData.gnssInterface->configMinGpsWeek(minGpsWeek);
927 } else {
928 LOC_LOGe("No gnss interface available for Location Control API");
929 }
930
931 pthread_mutex_unlock(&gDataMutex);
932 return id;
933 }
934
configDeadReckoningEngineParams(const DeadReckoningEngineConfig & dreConfig)935 uint32_t LocationControlAPI::configDeadReckoningEngineParams(
936 const DeadReckoningEngineConfig& dreConfig) {
937 uint32_t id = 0;
938 pthread_mutex_lock(&gDataMutex);
939
940 if (gData.gnssInterface != NULL) {
941 id = gData.gnssInterface->configDeadReckoningEngineParams(dreConfig);
942 } else {
943 LOC_LOGe("No gnss interface available for Location Control API");
944 }
945
946 pthread_mutex_unlock(&gDataMutex);
947 return id;
948 }
949
configEngineRunState(PositioningEngineMask engType,LocEngineRunState engState)950 uint32_t LocationControlAPI::configEngineRunState(
951 PositioningEngineMask engType, LocEngineRunState engState) {
952 uint32_t id = 0;
953 pthread_mutex_lock(&gDataMutex);
954
955 if (gData.gnssInterface != NULL) {
956 id = gData.gnssInterface->configEngineRunState(engType, engState);
957 } else {
958 LOC_LOGe("No gnss interface available for Location Control API");
959 }
960
961 pthread_mutex_unlock(&gDataMutex);
962 return id;
963 }
964
setOptInStatus(bool userConsent)965 uint32_t LocationControlAPI::setOptInStatus(bool userConsent) {
966 void* libHandle = nullptr;
967 uint32_t sessionId = 0;
968 setOptInStatusGetter* setter = (setOptInStatusGetter*)dlGetSymFromLib(libHandle,
969 "liblocationservice_glue.so", "setOptInStatus");
970 if (setter != nullptr) {
971 sessionId = (*setter)(userConsent, &gData.controlCallbacks.responseCb);
972 } else {
973 LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
974 }
975 return sessionId;
976 }
977