blob: 3a50c46b731973a08cb93a95a952bc3125fa6e73 [file] [log] [blame]
Michael Bestas3a0209e2023-05-04 01:15:47 +03001/* 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
39typedef const GnssInterface* (getGnssInterface)();
40typedef const GeofenceInterface* (getGeofenceInterface)();
41typedef const BatchingInterface* (getBatchingInterface)();
42typedef void (createOSFramework)();
43typedef void (destroyOSFramework)();
44
45// GTP services
46typedef uint32_t (setOptInStatusGetter)(bool userConsent, responseCallback* callback);
47typedef void (enableProviderGetter)();
48typedef void (disableProviderGetter)();
49typedef void (getSingleNetworkLocationGetter)(trackingCallback* callback);
50typedef void (stopNetworkLocationGetter)(trackingCallback* callback);
51
52typedef 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.
61typedef std::map<LocationAPI*, LocationAPIDestroyCbData>
62 LocationClientDestroyCbMap;
63
64typedef std::map<LocationAPI*, LocationCallbacks> LocationClientMap;
65typedef 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
75static LocationAPIData gData = {};
76static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER;
77static bool gGnssLoadFailed = false;
78static bool gBatchingLoadFailed = false;
79static bool gGeofenceLoadFailed = false;
80static uint32_t gOSFrameworkRefCount = 0;
81
82template <typename T1, typename T2>
83static 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
93static 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
104static 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
115static 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
125static 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
138static bool isBatchingClient(LocationCallbacks& locationCallbacks)
139{
140 return (locationCallbacks.batchingCb != nullptr);
141}
142
143static bool isGeofenceClient(LocationCallbacks& locationCallbacks)
144{
145 return (locationCallbacks.geofenceBreachCb != nullptr ||
146 locationCallbacks.geofenceStatusCb != nullptr);
147}
148
149
150void 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
177void onGnssRemoveClientCompleteCb (LocationAPI* client)
178{
179 client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GNSS_TYPE_BIT);
180}
181
182void onBatchingRemoveClientCompleteCb (LocationAPI* client)
183{
184 client->onRemoveClientCompleteCb (LOCATION_ADAPTER_BATCHING_TYPE_BIT);
185}
186
187void onGeofenceRemoveClientCompleteCb (LocationAPI* client)
188{
189 client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GEOFENCE_TYPE_BIT);
190}
191
192LocationAPI*
193LocationAPI::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
282void
283LocationAPI::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
351LocationAPI::LocationAPI()
352{
353 LOC_LOGD("LOCATION API CONSTRUCTOR");
354}
355
356// private destructor
357LocationAPI::~LocationAPI()
358{
359 LOC_LOGD("LOCATION API DESTRUCTOR");
360}
361
362void
363LocationAPI::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
432uint32_t
433LocationAPI::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
455void
456LocationAPI::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
476void
477LocationAPI::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
498uint32_t
499LocationAPI::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
515void
516LocationAPI::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
530void
531LocationAPI::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
545void
546LocationAPI::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
560uint32_t*
561LocationAPI::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
577void
578LocationAPI::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
592void
593LocationAPI::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
607void
608LocationAPI::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
622void
623LocationAPI::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
637void
638LocationAPI::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
652void 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
663void 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
674void 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
686void 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
698LocationControlAPI*
699LocationControlAPI::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
728void
729LocationControlAPI::destroy()
730{
731 delete this;
732}
733
734LocationControlAPI::LocationControlAPI()
735{
736 LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR");
737}
738
739LocationControlAPI::~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
749uint32_t
750LocationControlAPI::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
766void
767LocationControlAPI::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
781uint32_t*
782LocationControlAPI::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
798uint32_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
813uint32_t
814LocationControlAPI::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
830uint32_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
847uint32_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
862uint32_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
879uint32_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
893uint32_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
907uint32_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
921uint32_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
935uint32_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
950uint32_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
965uint32_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}