• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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