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