1eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
2eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh *
3eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * Redistribution and use in source and binary forms, with or without
4eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * modification, are permitted provided that the following conditions are
5eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * met:
6eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh *     * Redistributions of source code must retain the above copyright
7eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh *       notice, this list of conditions and the following disclaimer.
8eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh *     * Redistributions in binary form must reproduce the above
9eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh *       copyright notice, this list of conditions and the following
10eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh *       disclaimer in the documentation and/or other materials provided
11eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh *       with the distribution.
12eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh *     * Neither the name of The Linux Foundation nor the names of its
13eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh *       contributors may be used to endorse or promote products derived
14eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh *       from this software without specific prior written permission.
15eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh *
16eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh */
28eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#define LOG_TAG "LocSvc_LocationAPI"
29eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
30eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#include <location_interface.h>
31eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#include <dlfcn.h>
32eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#include <platform_lib_log_util.h>
33eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#include <pthread.h>
34eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh#include <map>
35eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
36eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhtypedef void* (getLocationInterface)();
37eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhtypedef std::map<LocationAPI*, LocationCallbacks> LocationClientMap;
38eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhtypedef struct {
39eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    LocationClientMap clientData;
40eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    LocationControlAPI* controlAPI;
41eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    LocationControlCallbacks controlCallbacks;
42eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    GnssInterface* gnssInterface;
43eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    GeofenceInterface* geofenceInterface;
44eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    FlpInterface* flpInterface;
45eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh} LocationAPIData;
46eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhstatic LocationAPIData gData = {};
47eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhstatic pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER;
48eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhstatic bool gGnssLoadFailed = false;
49eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhstatic bool gFlpLoadFailed = false;
50eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhstatic bool gGeofenceLoadFailed = false;
51eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
52eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhstatic bool needsGnssTrackingInfo(LocationCallbacks& locationCallbacks)
53eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
54eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    return (locationCallbacks.gnssLocationInfoCb != nullptr ||
55eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            locationCallbacks.gnssSvCb != nullptr ||
56eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            locationCallbacks.gnssNmeaCb != nullptr ||
57eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            locationCallbacks.gnssMeasurementsCb != nullptr);
58eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
59eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
60eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhstatic bool isGnssClient(LocationCallbacks& locationCallbacks)
61eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
62eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    return (locationCallbacks.gnssNiCb != nullptr ||
63eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            locationCallbacks.trackingCb != nullptr ||
64eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            locationCallbacks.gnssMeasurementsCb != nullptr);
65eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
66eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
67eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhstatic bool isFlpClient(LocationCallbacks& locationCallbacks)
68eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
69eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    return (locationCallbacks.trackingCb != nullptr ||
70eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            locationCallbacks.batchingCb != nullptr);
71eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
72eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
73eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhstatic bool isGeofenceClient(LocationCallbacks& locationCallbacks)
74eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
75eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    return (locationCallbacks.geofenceBreachCb != nullptr ||
76eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            locationCallbacks.geofenceStatusCb != nullptr);
77eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
78eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
79eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhstatic void* loadLocationInterface(const char* library, const char* name) {
80eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    LOC_LOGD("%s]: loading %s::%s ...", __func__, library, name);
81eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (NULL == library || NULL == name) {
82eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        return NULL;
83eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
84eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    getLocationInterface* getter = NULL;
85eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    const char *error = NULL;
86eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    dlerror();
87eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    void *handle = dlopen(library, RTLD_NOW);
88eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (NULL == handle || (error = dlerror()) != NULL)  {
89eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGW("dlopen for %s failed, error = %s", library, error);
90eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
91eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        getter = (getLocationInterface*)dlsym(handle, name);
92eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if ((error = dlerror()) != NULL)  {
93eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            LOC_LOGW("dlsym for %s::%s failed, error = %s", library, name, error);
94eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            getter = NULL;
95eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
96eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
97eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
98eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (NULL == getter) {
99eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        return (void*)getter;
100eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
101eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        return (*getter)();
102eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
103eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
104eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
105eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI*
106eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::createInstance(LocationCallbacks& locationCallbacks)
107eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
108eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (nullptr == locationCallbacks.capabilitiesCb ||
109eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        nullptr == locationCallbacks.responseCb ||
110eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        nullptr == locationCallbacks.collectiveResponseCb) {
111eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        return NULL;
112eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
113eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
114eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    LocationAPI* newLocationAPI = new LocationAPI();
115eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    bool requestedCapabilities = false;
116eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
117eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
118eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
119eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (isGnssClient(locationCallbacks)) {
120eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
121eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.gnssInterface =
122eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface");
123eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            if (NULL == gData.gnssInterface) {
124eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gGnssLoadFailed = true;
125eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
126eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            } else {
127eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gData.gnssInterface->initialize();
128eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            }
129eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
130eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL != gData.gnssInterface) {
131eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.gnssInterface->addClient(newLocationAPI, locationCallbacks);
132eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            if (!requestedCapabilities) {
133eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gData.gnssInterface->requestCapabilities(newLocationAPI);
134eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                requestedCapabilities = true;
135eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            }
136eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
137eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
138eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
139eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (isFlpClient(locationCallbacks)) {
140eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL == gData.flpInterface && !gFlpLoadFailed) {
141eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.flpInterface =
142eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface");
143eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            if (NULL == gData.flpInterface) {
144eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gFlpLoadFailed = true;
145eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__);
146eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            } else {
147eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gData.flpInterface->initialize();
148eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            }
149eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
150eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL != gData.flpInterface) {
151eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.flpInterface->addClient(newLocationAPI, locationCallbacks);
152eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            if (!requestedCapabilities) {
153eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gData.flpInterface->requestCapabilities(newLocationAPI);
154eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                requestedCapabilities = true;
155eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            }
156eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
157eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
158eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
159eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (isGeofenceClient(locationCallbacks)) {
160eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
161eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.geofenceInterface =
162eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                (GeofenceInterface*)loadLocationInterface("libgeofence.so", "getGeofenceInterface");
163eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            if (NULL == gData.geofenceInterface) {
164eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gGeofenceLoadFailed = true;
165eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
166eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            } else {
167eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gData.geofenceInterface->initialize();
168eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            }
169eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
170eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL != gData.geofenceInterface) {
171eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.geofenceInterface->addClient(newLocationAPI, locationCallbacks);
172eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            if (!requestedCapabilities) {
173eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gData.geofenceInterface->requestCapabilities(newLocationAPI);
174eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                requestedCapabilities = true;
175eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            }
176eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
177eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
178eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
179eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    gData.clientData[newLocationAPI] = locationCallbacks;
180eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
181eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
182eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
183eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    return newLocationAPI;
184eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
185eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
186eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
187eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::destroy()
188eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
189eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    delete this;
190eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
191eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
192eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::LocationAPI()
193eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
194eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    LOC_LOGD("LOCATION API CONSTRUCTOR");
195eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
196eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
197eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::~LocationAPI()
198eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
199eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    LOC_LOGD("LOCATION API DESTRUCTOR");
200eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
201eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
202eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    auto it = gData.clientData.find(this);
203eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (it != gData.clientData.end()) {
204eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (isGnssClient(it->second) && NULL != gData.gnssInterface) {
205eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.gnssInterface->removeClient(it->first);
206eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
207eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (isFlpClient(it->second) && NULL != gData.flpInterface) {
208eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.flpInterface->removeClient(it->first);
209eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
210eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (isGeofenceClient(it->second) && NULL != gData.geofenceInterface) {
211eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.geofenceInterface->removeClient(it->first);
212eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
213eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        gData.clientData.erase(it);
214eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
215eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: Location API client %p not found in client data",
216eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
217eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
218eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
219eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
220eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
221eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
222eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
223eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks)
224eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
225eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (nullptr == locationCallbacks.capabilitiesCb ||
226eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        nullptr == locationCallbacks.responseCb ||
227eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        nullptr == locationCallbacks.collectiveResponseCb) {
228eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        return;
229eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
230eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
231eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
232eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
233eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (isGnssClient(locationCallbacks)) {
234eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
235eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.gnssInterface =
236eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface");
237eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            if (NULL == gData.gnssInterface) {
238eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gGnssLoadFailed = true;
239eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
240eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            } else {
241eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gData.gnssInterface->initialize();
242eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            }
243eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
244eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL != gData.gnssInterface) {
245eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            // either adds new Client or updates existing Client
246eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.gnssInterface->addClient(this, locationCallbacks);
247eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
248eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
249eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
250eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (isFlpClient(locationCallbacks)) {
251eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL == gData.flpInterface && !gFlpLoadFailed) {
252eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.flpInterface =
253eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                (FlpInterface*)loadLocationInterface("libflp.so", "getFlpInterface");
254eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            if (NULL == gData.flpInterface) {
255eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gFlpLoadFailed = true;
256eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                LOC_LOGW("%s:%d]: No flp interface available", __func__, __LINE__);
257eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            } else {
258eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gData.flpInterface->initialize();
259eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            }
260eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
261eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL != gData.flpInterface) {
262eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            // either adds new Client or updates existing Client
263eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.flpInterface->addClient(this, locationCallbacks);
264eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
265eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
266eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
267eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (isGeofenceClient(locationCallbacks)) {
268eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
269eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.geofenceInterface =
270eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                (GeofenceInterface*)loadLocationInterface("libgeofence.so", "getGeofenceInterface");
271eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            if (NULL == gData.geofenceInterface) {
272eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gGeofenceLoadFailed = true;
273eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
274eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            } else {
275eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gData.geofenceInterface->initialize();
276eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            }
277eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
278eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL != gData.geofenceInterface) {
279eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            // either adds new Client or updates existing Client
280eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.geofenceInterface->addClient(this, locationCallbacks);
281eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
282eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
283eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
284eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    gData.clientData[this] = locationCallbacks;
285eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
286eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
287eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
288eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
289eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhuint32_t
290eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::startTracking(LocationOptions& locationOptions)
291eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
292eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    uint32_t id = 0;
293eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
294eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
295eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    auto it = gData.clientData.find(this);
296eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (it != gData.clientData.end()) {
297eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (gData.flpInterface != NULL && locationOptions.minDistance > 0) {
298eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            id = gData.flpInterface->startTracking(this, locationOptions);
299eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        } else if (gData.gnssInterface != NULL && needsGnssTrackingInfo(it->second)) {
300eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            id = gData.gnssInterface->startTracking(this, locationOptions);
301eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        } else if (gData.flpInterface != NULL) {
302eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            id = gData.flpInterface->startTracking(this, locationOptions);
303eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        } else if (gData.gnssInterface != NULL) {
304eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            id = gData.gnssInterface->startTracking(this, locationOptions);
305eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        } else {
306eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ",
307eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                     __func__, __LINE__, this);
308eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
309eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
310eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: Location API client %p not found in client data",
311eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
312eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
313eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
314eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
315eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    return id;
316eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
317eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
318eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
319eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::stopTracking(uint32_t id)
320eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
321eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
322eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
323eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    auto it = gData.clientData.find(this);
324eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (it != gData.clientData.end()) {
325eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        // we don't know if tracking was started on flp or gnss, so we call stop on both, where
326eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        // stopTracking call to the incorrect interface will fail without response back to client
327eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (gData.gnssInterface != NULL) {
328eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.gnssInterface->stopTracking(this, id);
329eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
330eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (gData.flpInterface != NULL) {
331eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.flpInterface->stopTracking(this, id);
332eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
333eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (gData.flpInterface == NULL && gData.gnssInterface == NULL) {
334eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ",
335eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                     __func__, __LINE__, this);
336eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
337eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
338eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: Location API client %p not found in client data",
339eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
340eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
341eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
342eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
343eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
344eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
345eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
346eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::updateTrackingOptions(uint32_t id, LocationOptions& locationOptions)
347eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
348eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
349eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
350eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    auto it = gData.clientData.find(this);
351eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (it != gData.clientData.end()) {
352eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        // we don't know if tracking was started on flp or gnss, so we call update on both, where
353eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        // updateTracking call to the incorrect interface will fail without response back to client
354eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (gData.gnssInterface != NULL) {
355eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.gnssInterface->updateTrackingOptions(this, id, locationOptions);
356eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
357eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (gData.flpInterface != NULL) {
358eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.flpInterface->updateTrackingOptions(this, id, locationOptions);
359eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
360eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (gData.flpInterface == NULL && gData.gnssInterface == NULL) {
361eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            LOC_LOGE("%s:%d]: No gnss/flp interface available for Location API client %p ",
362eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                     __func__, __LINE__, this);
363eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
364eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
365eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: Location API client %p not found in client data",
366eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
367eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
368eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
369eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
370eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
371eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
372eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhuint32_t
373eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::startBatching(LocationOptions& locationOptions, BatchingOptions &batchingOptions)
374eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
375eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    uint32_t id = 0;
376eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
377eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
378eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.flpInterface != NULL) {
379eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        id = gData.flpInterface->startBatching(this, locationOptions, batchingOptions);
380eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
381eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
382eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
383eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
384eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
385eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
386eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    return id;
387eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
388eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
389eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
390eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::stopBatching(uint32_t id)
391eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
392eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
393eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
394eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.flpInterface != NULL) {
395eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        gData.flpInterface->stopBatching(this, id);
396eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
397eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
398eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
399eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
400eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
401eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
402eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
403eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
404eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
405eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::updateBatchingOptions(uint32_t id,
406eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LocationOptions& locationOptions, BatchingOptions& batchOptions)
407eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
408eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
409eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
410eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.flpInterface != NULL) {
411eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        gData.flpInterface->updateBatchingOptions(this,
412eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                                                  id,
413eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                                                  locationOptions,
414eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                                                  batchOptions);
415eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
416eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
417eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
418eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
419eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
420eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
421eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
422eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
423eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
424eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::getBatchedLocations(uint32_t id, size_t count)
425eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
426eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
427eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
428eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.flpInterface != NULL) {
429eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        gData.flpInterface->getBatchedLocations(this, id, count);
430eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
431eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No flp interface available for Location API client %p ",
432eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
433eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
434eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
435eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
436eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
437eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
438eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhuint32_t*
439eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::addGeofences(size_t count, GeofenceOption* options, GeofenceInfo* info)
440eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
441eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    uint32_t* ids = NULL;
442eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
443eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
444eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.geofenceInterface != NULL) {
445eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        ids = gData.geofenceInterface->addGeofences(this, count, options, info);
446eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
447eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
448eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
449eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
450eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
451eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
452eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    return ids;
453eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
454eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
455eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
456eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::removeGeofences(size_t count, uint32_t* ids)
457eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
458eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
459eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
460eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.geofenceInterface != NULL) {
461eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        gData.geofenceInterface->removeGeofences(this, count, ids);
462eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
463eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
464eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
465eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
466eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
467eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
468eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
469eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
470eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
471eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options)
472eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
473eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
474eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
475eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.geofenceInterface != NULL) {
476eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        gData.geofenceInterface->modifyGeofences(this, count, ids, options);
477eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
478eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
479eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
480eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
481eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
482eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
483eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
484eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
485eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
486eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::pauseGeofences(size_t count, uint32_t* ids)
487eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
488eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
489eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
490eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.geofenceInterface != NULL) {
491eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        gData.geofenceInterface->pauseGeofences(this, count, ids);
492eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
493eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
494eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
495eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
496eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
497eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
498eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
499eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
500eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
501eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::resumeGeofences(size_t count, uint32_t* ids)
502eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
503eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
504eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
505eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.geofenceInterface != NULL) {
506eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        gData.geofenceInterface->resumeGeofences(this, count, ids);
507eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
508eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
509eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
510eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
511eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
512eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
513eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
514eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
515eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
516eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationAPI::gnssNiResponse(uint32_t id, GnssNiResponse response)
517eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
518eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
519eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
520eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.gnssInterface != NULL) {
521eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        gData.gnssInterface->gnssNiResponse(this, id, response);
522eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
523eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
524eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
525eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
526eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
527eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
528eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
529eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
530eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationControlAPI*
531eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks)
532eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
533eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    LocationControlAPI* controlAPI = NULL;
534eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
535eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
536eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) {
537eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
538eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.gnssInterface =
539eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                (GnssInterface*)loadLocationInterface("libgnss.so", "getGnssInterface");
540eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            if (NULL == gData.gnssInterface) {
541eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gGnssLoadFailed = true;
542eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
543eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            } else {
544eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                gData.gnssInterface->initialize();
545eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            }
546eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
547eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        if (NULL != gData.gnssInterface) {
548eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.controlAPI = new LocationControlAPI();
549eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.controlCallbacks = locationControlCallbacks;
550eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            gData.gnssInterface->setControlCallbacks(locationControlCallbacks);
551eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh            controlAPI = gData.controlAPI;
552eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        }
553eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
554eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
555eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
556eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    return controlAPI;
557eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
558eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
559eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
560eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationControlAPI::destroy()
561eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
562eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    delete this;
563eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
564eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
565eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationControlAPI::LocationControlAPI()
566eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
567eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR");
568eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
569eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
570eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationControlAPI::~LocationControlAPI()
571eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
572eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    LOC_LOGD("LOCATION CONTROL API DESTRUCTOR");
573eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
574eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
575eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    gData.controlAPI = NULL;
576eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
577eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
578eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
579eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
580eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhuint32_t
581eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationControlAPI::enable(LocationTechnologyType techType)
582eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
583eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    uint32_t id = 0;
584eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
585eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
586eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.gnssInterface != NULL) {
587eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        id = gData.gnssInterface->enable(techType);
588eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
589eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
590eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
591eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
592eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
593eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
594eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    return id;
595eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
596eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
597eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhvoid
598eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationControlAPI::disable(uint32_t id)
599eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
600eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
601eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
602eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.gnssInterface != NULL) {
603eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        gData.gnssInterface->disable(id);
604eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
605eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
606eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
607eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
608eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
609eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
610eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
611eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
612eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhuint32_t*
613eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationControlAPI::gnssUpdateConfig(GnssConfig config)
614eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
615eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    uint32_t* ids = NULL;
616eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
617eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
618eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.gnssInterface != NULL) {
619eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        ids = gData.gnssInterface->gnssUpdateConfig(config);
620eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
621eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
622eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
623eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
624eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
625eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
626eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    return ids;
627eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
628eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
629eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanhuint32_t
630eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain VongsouvanhLocationControlAPI::gnssDeleteAidingData(GnssAidingData& data)
631eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh{
632eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    uint32_t id = 0;
633eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_lock(&gDataMutex);
634eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
635eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    if (gData.gnssInterface != NULL) {
636eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        id = gData.gnssInterface->gnssDeleteAidingData(data);
637eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    } else {
638eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh        LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
639eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh                 __func__, __LINE__, this);
640eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    }
641eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh
642eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    pthread_mutex_unlock(&gDataMutex);
643eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh    return id;
644eee4b7537bec1ef4198a5c0c9cfb8ba232ad60cbAlain Vongsouvanh}
645