sm8450-common: Import gps from LA.VENDOR.1.0.r1-12800-WAIPIO.0

Change-Id: Ia76265a8c3326f2b5f9f260ce98807276af80ee3
This commit is contained in:
Arian
2024-01-27 01:37:39 +01:00
parent 106355e12e
commit b9fdaff70a
286 changed files with 72332 additions and 0 deletions

36
gps/location/Android.bp Normal file
View File

@@ -0,0 +1,36 @@
cc_library_shared {
name: "liblocation_api",
vendor: true,
shared_libs: [
"libutils",
"libcutils",
"libgps.utils",
"libdl",
"liblog",
],
srcs: [
"LocationAPI.cpp",
"LocationAPIClientBase.cpp",
],
cflags: ["-fno-short-enums"] + GNSS_CFLAGS,
header_libs: [
"libloc_pla_headers",
"libgps.utils_headers",
],
}
cc_library_headers {
name: "liblocation_api_headers",
export_include_dirs: ["."],
vendor: true,
}

451
gps/location/ILocationAPI.h Normal file
View File

@@ -0,0 +1,451 @@
/* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ILOCATIONAPI_H
#define ILOCATIONAPI_H
#include "LocationDataTypes.h"
class ILocationAPI
{
public:
virtual ~ILocationAPI(){};
/** @brief Updates/changes the callbacks that will be called.
mandatory callbacks must be present for callbacks to be successfully updated
no return value */
virtual void updateCallbacks(LocationCallbacks&) = 0;
/* ================================== TRACKING ================================== */
/** @brief Starts a tracking session, which returns a session id that will be
used by the other tracking APIs and also in the responseCallback to match command
with response. locations are reported on the registered trackingCallback
periodically according to LocationOptions.
@return session id
responseCallback returns:
LOCATION_ERROR_SUCCESS if session was successfully started
LOCATION_ERROR_ALREADY_STARTED if a startTracking session is already in progress
LOCATION_ERROR_CALLBACK_MISSING if no trackingCallback was passed
LOCATION_ERROR_INVALID_PARAMETER if LocationOptions parameter is invalid */
virtual uint32_t startTracking(TrackingOptions&) = 0;
/** @brief Stops a tracking session associated with id parameter.
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */
virtual void stopTracking(uint32_t id) = 0;
/** @brief Changes the LocationOptions of a tracking session associated with id.
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if LocationOptions parameters are invalid
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */
virtual void updateTrackingOptions(uint32_t id, TrackingOptions&) = 0;
/* ================================== BATCHING ================================== */
/** @brief starts a batching session, which returns a session id that will be
used by the other batching APIs and also in the responseCallback to match command
with response. locations are reported on the batchingCallback passed in createInstance
periodically according to LocationOptions. A batching session starts tracking on
the low power processor and delivers them in batches by the batchingCallback when
the batch is full or when getBatchedLocations is called. This allows for the processor
that calls this API to sleep when the low power processor can batch locations in the
backgroup and wake up the processor calling the API only when the batch is full, thus
saving power.
@return session id
responseCallback returns:
LOCATION_ERROR_SUCCESS if session was successful
LOCATION_ERROR_ALREADY_STARTED if a startBatching session is already in progress
LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback
LOCATION_ERROR_INVALID_PARAMETER if a parameter is invalid
LOCATION_ERROR_NOT_SUPPORTED if batching is not supported */
virtual uint32_t startBatching(BatchingOptions&) = 0;
/** @brief Stops a batching session associated with id parameter.
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id is not associated with batching session */
virtual void stopBatching(uint32_t id) = 0;
/** @brief Changes the LocationOptions of a batching session associated with id.
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if LocationOptions parameters are invalid
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */
virtual void updateBatchingOptions(uint32_t id, BatchingOptions&) = 0;
/** @brief Gets a number of locations that are currently stored/batched
on the low power processor, delivered by the batchingCallback passed in createInstance.
Location are then deleted from the batch stored on the low power processor.
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful, will be followed by batchingCallback call
LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */
virtual void getBatchedLocations(uint32_t id, size_t count) = 0;
/* ================================== GEOFENCE ================================== */
/** @brief Adds any number of geofences and returns an array of geofence ids that
will be used by the other geofence APIs and also in the collectiveResponseCallback to
match command with response. The geofenceBreachCallback will deliver the status of each
geofence according to the GeofenceOption for each. The geofence id array returned will
be valid until the collectiveResponseCallback is called and has returned.
@return id array
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if session was successful
LOCATION_ERROR_CALLBACK_MISSING if no geofenceBreachCallback
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
LOCATION_ERROR_NOT_SUPPORTED if geofence is not supported */
virtual uint32_t* addGeofences(size_t count, GeofenceOption*, GeofenceInfo*) = 0;
/** @brief Removes any number of geofences. Caller should delete ids array after
removeGeofences returneds.
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */
virtual void removeGeofences(size_t count, uint32_t* ids) = 0;
/** @brief Modifies any number of geofences. Caller should delete ids array after
modifyGeofences returns.
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid */
virtual void modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options) = 0;
/** @brief Pauses any number of geofences, which is similar to removeGeofences,
only that they can be resumed at any time. Caller should delete ids array after
pauseGeofences returns.
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */
virtual void pauseGeofences(size_t count, uint32_t* ids) = 0;
/** @brief Resumes any number of geofences that are currently paused. Caller should
delete ids array after resumeGeofences returns.
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */
virtual void resumeGeofences(size_t count, uint32_t* ids) = 0;
/* ================================== GNSS ====================================== */
/** @brief gnssNiResponse is called in response to a gnssNiCallback.
responseCallback returns:
LOCATION_ERROR_SUCCESS if session was successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters in GnssNiResponse are invalid
LOCATION_ERROR_ID_UNKNOWN if id does not match a gnssNiCallback */
virtual void gnssNiResponse(uint32_t id, GnssNiResponse response) = 0;
};
class ILocationControlAPI
{
public:
virtual ~ILocationControlAPI(){};
/** @brief Updates the gnss specific configuration, which returns a session id array
with an id for each of the bits set in GnssConfig.flags, order from low bits to high bits.
The response for each config that is set will be returned in collectiveResponseCallback.
The session id array returned will be valid until the collectiveResponseCallback is called
and has returned. This effect is global for all clients of ILocationAPI.
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if session was successful
LOCATION_ERROR_INVALID_PARAMETER if any other parameters are invalid
LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */
virtual uint32_t* gnssUpdateConfig(const GnssConfig& config) = 0;
/** @brief Delete specific gnss aiding data for testing, which returns a session id
that will be returned in responseCallback to match command with response.
Only allowed in userdebug builds. This effect is global for all clients of ILocationAPI.
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
LOCATION_ERROR_NOT_SUPPORTED if build is not userdebug */
virtual uint32_t gnssDeleteAidingData(GnssAidingData& data) = 0;
/** @brief
Configure the constellation and SVs to be used by the GNSS engine on
modem.
@param
constellationEnablementConfig: configuration to enable/disable SV
constellation to be used by SPE engine. When size in
constellationEnablementConfig is set to 0, this indicates to reset SV
constellation configuration to modem NV default.
blacklistSvConfig: configuration to blacklist or unblacklist SVs
used by SPE engine
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configConstellations(
const GnssSvTypeConfig& constellationEnablementConfig,
const GnssSvIdConfig& blacklistSvConfig) = 0;
/** @brief
Configure the secondary band of constellations to be used by
the GNSS engine on modem.
@param
secondaryBandConfig: configuration the secondary band usage
for SPE engine
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configConstellationSecondaryBand(
const GnssSvTypeConfig& secondaryBandConfig) = 0;
/** @brief
Enable or disable the constrained time uncertainty feature.
@param
enable: true to enable the constrained time uncertainty
feature and false to disable the constrainted time
uncertainty feature.
@param
tuncThreshold: this specifies the time uncertainty threshold
that gps engine need to maintain, in units of milli-seconds.
Default is 0.0 meaning that modem default value of time
uncertainty threshold will be used. This parameter is
ignored when requesting to disable this feature.
@param
energyBudget: this specifies the power budget that gps
engine is allowed to spend to maintain the time uncertainty.
Default is 0 meaning that GPS engine is not constained by
power budget and can spend as much power as needed. The
parameter need to be specified in units of 0.1 milli watt
second. This parameter is ignored requesting to disable this
feature.
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters
are invalid
*/
virtual uint32_t configConstrainedTimeUncertainty(
bool enable, float tuncThreshold = 0.0,
uint32_t energyBudget = 0) = 0;
/** @brief
Enable or disable position assisted clock estimator feature.
@param
enable: true to enable position assisted clock estimator and
false to disable the position assisted clock estimator
feature.
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configPositionAssistedClockEstimator(bool enable) = 0;
/** @brief
Sets the lever arm parameters for the vehicle.
@param
configInfo: lever arm configuration info regarding below two
types of lever arm info:
a: GNSS Antenna w.r.t the origin at the IMU e.g.: inertial
measurement unit.
b: lever arm parameters regarding the OPF (output frame)
w.r.t the origin (at the GPS Antenna). Vehicle manufacturers
prefer the position output to be tied to a specific point in
the vehicle rather than where the antenna is placed
(midpoint of the rear axle is typical).
Caller can choose types of lever arm info to configure via the
leverMarkTypeMask.
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configLeverArm(const LeverArmConfigInfo& configInfo) = 0;
/** @brief
Configure the robust location setting.
@param
enable: true to enable robust location and false to disable
robust location.
@param
enableForE911: true to enable robust location when device is on
E911 session and false to disable on E911 session.
This parameter is only valid if robust location is enabled.
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configRobustLocation(bool enable, bool enableForE911) = 0;
/** @brief
Config the minimum GPS week used by modem GNSS engine.
@param
minGpsWeek: minimum GPS week to be used by modem GNSS engine.
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configMinGpsWeek(uint16_t minGpsWeek) = 0;
/** @brief
Configure the vehicle body-to-Sensor mount parameters and
other parameters for dead reckoning position engine.
@param
dreConfig: vehicle body-to-Sensor mount angles and other
parameters.
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configDeadReckoningEngineParams(const DeadReckoningEngineConfig& dreConfig)=0;
/** @brief
This API is used to instruct the specified engine to be in
the pause/resume state. <br/>
When the engine is placed in paused state, the engine will
stop. If there is an on-going session, engine will no longer
produce fixes. In the paused state, calling API to delete
aiding data from the paused engine may not have effect.
Request to delete Aiding data shall be issued after
engine resume. <br/>
Currently, only DRE engine will support pause/resume
request. responseCb() will return not supported when request
is made to pause/resume none-DRE engine. <br/>
Request to pause/resume DRE engine can be made with or
without an on-going session. With QDR engine, on resume,
GNSS position & heading re-acquisition is needed for DR
engine to engage. If DR engine is already in the requested
state, the request will be no-op. <br/>
@param
engType: the engine that is instructed to change its run
state. <br/>
engState: the new engine run state that the engine is
instructed to be in. <br/>
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configEngineRunState(PositioningEngineMask engType,
LocEngineRunState engState) = 0;
/** @brief
This API is used to config the NMEA sentence types.
Without prior calling this API, all NMEA sentences supported
in the system, as defined in NmeaTypesMask, will get
generated and delivered to all the location clients that
register to receive NMEA sentences.
The NMEA sentence types are per-device setting and calling
this API will impact all the location api clients that
register to receive NMEA sentences. This API call is not
incremental and the new NMEA sentence types will completely
overwrite the previous call.
If one or more unspecified bits are set in the NMEA mask,
those bits will be ignored, but the rest of the
configuration will get applied.
Please note that the configured NMEA sentence types are not
persistent.
@param
enabledNmeaTypes: specify the set of NMEA sentences the
device will generate and deliver to the location api clients
that register to receive NMEA sentences. <br/>
@return
A session id that will be returned in responseCallback to
match command with response.
*/
virtual uint32_t configOutputNmeaTypes(
GnssNmeaTypesMask enabledNmeaTypes) = 0;
/** @brief
This API is used to send platform power events to GNSS adapters in order
to handle GNSS sessions as per platform power event.
@param
powerState: Current vehicle/platform power state.
@return
No return value.
*/
virtual void powerStateEvent(PowerStateType powerState) {};
};
#endif /* ILOCATIONAPI_H */

View File

@@ -0,0 +1,985 @@
/* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define LOG_NDEBUG 0
#define LOG_TAG "LocSvc_LocationAPI"
#include <location_interface.h>
#include <dlfcn.h>
#include <loc_pla.h>
#include <log_util.h>
#include <pthread.h>
#include <map>
#include <loc_misc_utils.h>
typedef const GnssInterface* (getGnssInterface)();
typedef const GeofenceInterface* (getGeofenceInterface)();
typedef const BatchingInterface* (getBatchingInterface)();
// GTP services
typedef void (enableProviderGetter)();
typedef void (disableProviderGetter)();
typedef void (getSingleNetworkLocationGetter)(trackingCallback* callback);
typedef void (stopNetworkLocationGetter)(trackingCallback* callback);
typedef struct {
// bit mask of the adpaters that we need to wait for the removeClientCompleteCallback
// before we invoke the registered locationApiDestroyCompleteCallback
LocationAdapterTypeMask waitAdapterMask;
locationApiDestroyCompleteCallback destroyCompleteCb;
} LocationAPIDestroyCbData;
// This is the map for the client that has requested destroy with
// destroy callback provided.
typedef std::map<LocationAPI*, LocationAPIDestroyCbData>
LocationClientDestroyCbMap;
typedef std::map<LocationAPI*, LocationCallbacks> LocationClientMap;
typedef struct {
LocationClientMap clientData;
LocationClientDestroyCbMap destroyClientData;
LocationControlAPI* controlAPI;
LocationControlCallbacks controlCallbacks;
GnssInterface* gnssInterface;
GeofenceInterface* geofenceInterface;
BatchingInterface* batchingInterface;
} LocationAPIData;
static LocationAPIData gData = {};
static pthread_mutex_t gDataMutex = PTHREAD_MUTEX_INITIALIZER;
static bool gGnssLoadFailed = false;
static bool gBatchingLoadFailed = false;
static bool gGeofenceLoadFailed = false;
template <typename T1, typename T2>
static const T1* loadLocationInterface(const char* library, const char* name) {
void* libhandle = nullptr;
T2* getter = (T2*)dlGetSymFromLib(libhandle, library, name);
if (nullptr == getter) {
return (const T1*) getter;
}else {
return (*getter)();
}
}
static void loadLibGnss() {
if (NULL == gData.gnssInterface && !gGnssLoadFailed) {
gData.gnssInterface =
(GnssInterface*)loadLocationInterface<GnssInterface,
getGnssInterface>("libgnss.so", "getGnssInterface");
if (NULL == gData.gnssInterface) {
gGnssLoadFailed = true;
LOC_LOGW("%s:%d]: No gnss interface available", __func__, __LINE__);
} else {
gData.gnssInterface->initialize();
}
}
}
static void loadLibBatching() {
if (NULL == gData.batchingInterface && !gBatchingLoadFailed) {
gData.batchingInterface =
(BatchingInterface*)loadLocationInterface<BatchingInterface,
getBatchingInterface>("libbatching.so", "getBatchingInterface");
if (NULL == gData.batchingInterface) {
gBatchingLoadFailed = true;
LOC_LOGW("%s:%d]: No batching interface available", __func__, __LINE__);
} else {
gData.batchingInterface->initialize();
}
}
}
static void loadLibGeofencing() {
if (NULL == gData.geofenceInterface && !gGeofenceLoadFailed) {
gData.geofenceInterface =
(GeofenceInterface*)loadLocationInterface<GeofenceInterface,
getGeofenceInterface>("libgeofencing.so", "getGeofenceInterface");
if (NULL == gData.geofenceInterface) {
gGeofenceLoadFailed = true;
LOC_LOGW("%s:%d]: No geofence interface available", __func__, __LINE__);
} else {
gData.geofenceInterface->initialize();
}
}
}
static bool needsGnssTrackingInfo(LocationCallbacks& locationCallbacks)
{
return (locationCallbacks.gnssLocationInfoCb != nullptr ||
locationCallbacks.engineLocationsInfoCb != nullptr ||
locationCallbacks.gnssSvCb != nullptr ||
locationCallbacks.gnssNmeaCb != nullptr ||
locationCallbacks.gnssDataCb != nullptr ||
locationCallbacks.gnssMeasurementsCb != nullptr ||
locationCallbacks.gnssNHzMeasurementsCb != nullptr);
}
static bool isGnssClient(LocationCallbacks& locationCallbacks)
{
return (locationCallbacks.gnssNiCb != nullptr ||
locationCallbacks.trackingCb != nullptr ||
locationCallbacks.gnssLocationInfoCb != nullptr ||
locationCallbacks.engineLocationsInfoCb != nullptr ||
locationCallbacks.gnssSvCb != nullptr ||
locationCallbacks.gnssNmeaCb != nullptr ||
locationCallbacks.gnssDataCb != nullptr ||
locationCallbacks.gnssMeasurementsCb != nullptr ||
locationCallbacks.gnssNHzMeasurementsCb != nullptr ||
locationCallbacks.locationSystemInfoCb != nullptr);
}
static bool isBatchingClient(LocationCallbacks& locationCallbacks)
{
return (locationCallbacks.batchingCb != nullptr);
}
static bool isGeofenceClient(LocationCallbacks& locationCallbacks)
{
return (locationCallbacks.geofenceBreachCb != nullptr ||
locationCallbacks.geofenceStatusCb != nullptr);
}
void LocationAPI::onRemoveClientCompleteCb (LocationAdapterTypeMask adapterType)
{
bool invokeCallback = false;
locationApiDestroyCompleteCallback destroyCompleteCb;
LOC_LOGd("adatper type %x", adapterType);
pthread_mutex_lock(&gDataMutex);
auto it = gData.destroyClientData.find(this);
if (it != gData.destroyClientData.end()) {
it->second.waitAdapterMask &= ~adapterType;
if (it->second.waitAdapterMask == 0) {
invokeCallback = true;
destroyCompleteCb = it->second.destroyCompleteCb;
gData.destroyClientData.erase(it);
}
}
pthread_mutex_unlock(&gDataMutex);
if (invokeCallback) {
LOC_LOGd("invoke client destroy cb");
if (!destroyCompleteCb) {
(destroyCompleteCb) ();
}
delete this;
}
}
void onGnssRemoveClientCompleteCb (LocationAPI* client)
{
client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GNSS_TYPE_BIT);
}
void onBatchingRemoveClientCompleteCb (LocationAPI* client)
{
client->onRemoveClientCompleteCb (LOCATION_ADAPTER_BATCHING_TYPE_BIT);
}
void onGeofenceRemoveClientCompleteCb (LocationAPI* client)
{
client->onRemoveClientCompleteCb (LOCATION_ADAPTER_GEOFENCE_TYPE_BIT);
}
LocationAPI*
LocationAPI::createInstance (LocationCallbacks& locationCallbacks)
{
if (nullptr == locationCallbacks.capabilitiesCb ||
nullptr == locationCallbacks.responseCb ||
nullptr == locationCallbacks.collectiveResponseCb) {
LOC_LOGe("missing mandatory callback, return null");
return NULL;
}
LocationAPI* newLocationAPI = new LocationAPI();
bool requestedCapabilities = false;
pthread_mutex_lock(&gDataMutex);
if (isGnssClient(locationCallbacks)) {
loadLibGnss();
if (NULL != gData.gnssInterface) {
gData.gnssInterface->addClient(newLocationAPI, locationCallbacks);
if (!requestedCapabilities) {
gData.gnssInterface->requestCapabilities(newLocationAPI);
requestedCapabilities = true;
}
}
}
if (isBatchingClient(locationCallbacks)) {
loadLibBatching();
if (NULL != gData.batchingInterface) {
gData.batchingInterface->addClient(newLocationAPI, locationCallbacks);
if (!requestedCapabilities) {
gData.batchingInterface->requestCapabilities(newLocationAPI);
requestedCapabilities = true;
}
}
}
if (isGeofenceClient(locationCallbacks)) {
loadLibGeofencing();
if (NULL != gData.geofenceInterface) {
gData.geofenceInterface->addClient(newLocationAPI, locationCallbacks);
if (!requestedCapabilities) {
gData.geofenceInterface->requestCapabilities(newLocationAPI);
requestedCapabilities = true;
}
}
}
if (!requestedCapabilities && locationCallbacks.capabilitiesCb != nullptr) {
loadLibGnss();
if (NULL != gData.gnssInterface) {
gData.gnssInterface->addClient(newLocationAPI, locationCallbacks);
gData.gnssInterface->requestCapabilities(newLocationAPI);
requestedCapabilities = true;
}
}
gData.clientData[newLocationAPI] = locationCallbacks;
pthread_mutex_unlock(&gDataMutex);
return newLocationAPI;
}
void
LocationAPI::destroy(locationApiDestroyCompleteCallback destroyCompleteCb)
{
bool invokeDestroyCb = false;
pthread_mutex_lock(&gDataMutex);
auto it = gData.clientData.find(this);
if (it != gData.clientData.end()) {
bool removeFromGnssInf = (NULL != gData.gnssInterface);
bool removeFromBatchingInf = (NULL != gData.batchingInterface);
bool removeFromGeofenceInf = (NULL != gData.geofenceInterface);
bool needToWait = (removeFromGnssInf || removeFromBatchingInf || removeFromGeofenceInf);
LOC_LOGe("removeFromGnssInf: %d, removeFromBatchingInf: %d, removeFromGeofenceInf: %d,"
"needToWait: %d", removeFromGnssInf, removeFromBatchingInf, removeFromGeofenceInf,
needToWait);
if ((NULL != destroyCompleteCb) && (true == needToWait)) {
LocationAPIDestroyCbData destroyCbData = {};
destroyCbData.destroyCompleteCb = destroyCompleteCb;
// record down from which adapter we need to wait for the destroy complete callback
// only when we have received all the needed callbacks from all the associated stacks,
// we shall notify the client.
destroyCbData.waitAdapterMask =
(removeFromGnssInf ? LOCATION_ADAPTER_GNSS_TYPE_BIT : 0);
destroyCbData.waitAdapterMask |=
(removeFromBatchingInf ? LOCATION_ADAPTER_BATCHING_TYPE_BIT : 0);
destroyCbData.waitAdapterMask |=
(removeFromGeofenceInf ? LOCATION_ADAPTER_GEOFENCE_TYPE_BIT : 0);
gData.destroyClientData[this] = destroyCbData;
LOC_LOGi("destroy data stored in the map: 0x%x", destroyCbData.waitAdapterMask);
}
if (removeFromGnssInf) {
gData.gnssInterface->removeClient(it->first,
onGnssRemoveClientCompleteCb);
}
if (removeFromBatchingInf) {
gData.batchingInterface->removeClient(it->first,
onBatchingRemoveClientCompleteCb);
}
if (removeFromGeofenceInf) {
gData.geofenceInterface->removeClient(it->first,
onGeofenceRemoveClientCompleteCb);
}
gData.clientData.erase(it);
if (!needToWait) {
invokeDestroyCb = true;
}
} else {
LOC_LOGE("%s:%d]: Location API client %p not found in client data",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
if (invokeDestroyCb) {
if (!destroyCompleteCb) {
(destroyCompleteCb) ();
}
delete this;
}
}
LocationAPI::LocationAPI()
{
LOC_LOGD("LOCATION API CONSTRUCTOR");
}
// private destructor
LocationAPI::~LocationAPI()
{
LOC_LOGD("LOCATION API DESTRUCTOR");
}
void
LocationAPI::updateCallbacks(LocationCallbacks& locationCallbacks)
{
if (nullptr == locationCallbacks.capabilitiesCb ||
nullptr == locationCallbacks.responseCb ||
nullptr == locationCallbacks.collectiveResponseCb) {
return;
}
pthread_mutex_lock(&gDataMutex);
if (isGnssClient(locationCallbacks)) {
loadLibGnss();
if (NULL != gData.gnssInterface) {
// either adds new Client or updates existing Client
gData.gnssInterface->addClient(this, locationCallbacks);
}
}
if (isBatchingClient(locationCallbacks)) {
loadLibBatching();
if (NULL != gData.batchingInterface) {
// either adds new Client or updates existing Client
gData.batchingInterface->addClient(this, locationCallbacks);
}
}
if (isGeofenceClient(locationCallbacks)) {
loadLibGeofencing();
if (NULL != gData.geofenceInterface) {
// either adds new Client or updates existing Client
gData.geofenceInterface->addClient(this, locationCallbacks);
}
}
gData.clientData[this] = locationCallbacks;
pthread_mutex_unlock(&gDataMutex);
}
uint32_t
LocationAPI::startTracking(TrackingOptions& trackingOptions)
{
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
auto it = gData.clientData.find(this);
if (it != gData.clientData.end()) {
if (NULL != gData.gnssInterface) {
id = gData.gnssInterface->startTracking(this, trackingOptions);
} else {
LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
__func__, __LINE__, this);
}
} else {
LOC_LOGE("%s:%d]: Location API client %p not found in client data",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
void
LocationAPI::stopTracking(uint32_t id)
{
pthread_mutex_lock(&gDataMutex);
auto it = gData.clientData.find(this);
if (it != gData.clientData.end()) {
if (gData.gnssInterface != NULL) {
gData.gnssInterface->stopTracking(this, id);
} else {
LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
__func__, __LINE__, this);
}
} else {
LOC_LOGE("%s:%d]: Location API client %p not found in client data",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
}
void
LocationAPI::updateTrackingOptions(
uint32_t id, TrackingOptions& trackingOptions)
{
pthread_mutex_lock(&gDataMutex);
auto it = gData.clientData.find(this);
if (it != gData.clientData.end()) {
if (gData.gnssInterface != NULL) {
gData.gnssInterface->updateTrackingOptions(this, id, trackingOptions);
} else {
LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
__func__, __LINE__, this);
}
} else {
LOC_LOGE("%s:%d]: Location API client %p not found in client data",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
}
uint32_t
LocationAPI::startBatching(BatchingOptions &batchingOptions)
{
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (NULL != gData.batchingInterface) {
id = gData.batchingInterface->startBatching(this, batchingOptions);
} else {
LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
void
LocationAPI::stopBatching(uint32_t id)
{
pthread_mutex_lock(&gDataMutex);
if (NULL != gData.batchingInterface) {
gData.batchingInterface->stopBatching(this, id);
} else {
LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
}
void
LocationAPI::updateBatchingOptions(uint32_t id, BatchingOptions& batchOptions)
{
pthread_mutex_lock(&gDataMutex);
if (NULL != gData.batchingInterface) {
gData.batchingInterface->updateBatchingOptions(this, id, batchOptions);
} else {
LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
}
void
LocationAPI::getBatchedLocations(uint32_t id, size_t count)
{
pthread_mutex_lock(&gDataMutex);
if (gData.batchingInterface != NULL) {
gData.batchingInterface->getBatchedLocations(this, id, count);
} else {
LOC_LOGE("%s:%d]: No batching interface available for Location API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
}
uint32_t*
LocationAPI::addGeofences(size_t count, GeofenceOption* options, GeofenceInfo* info)
{
uint32_t* ids = NULL;
pthread_mutex_lock(&gDataMutex);
if (gData.geofenceInterface != NULL) {
ids = gData.geofenceInterface->addGeofences(this, count, options, info);
} else {
LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
return ids;
}
void
LocationAPI::removeGeofences(size_t count, uint32_t* ids)
{
pthread_mutex_lock(&gDataMutex);
if (gData.geofenceInterface != NULL) {
gData.geofenceInterface->removeGeofences(this, count, ids);
} else {
LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
}
void
LocationAPI::modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options)
{
pthread_mutex_lock(&gDataMutex);
if (gData.geofenceInterface != NULL) {
gData.geofenceInterface->modifyGeofences(this, count, ids, options);
} else {
LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
}
void
LocationAPI::pauseGeofences(size_t count, uint32_t* ids)
{
pthread_mutex_lock(&gDataMutex);
if (gData.geofenceInterface != NULL) {
gData.geofenceInterface->pauseGeofences(this, count, ids);
} else {
LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
}
void
LocationAPI::resumeGeofences(size_t count, uint32_t* ids)
{
pthread_mutex_lock(&gDataMutex);
if (gData.geofenceInterface != NULL) {
gData.geofenceInterface->resumeGeofences(this, count, ids);
} else {
LOC_LOGE("%s:%d]: No geofence interface available for Location API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
}
void
LocationAPI::gnssNiResponse(uint32_t id, GnssNiResponse response)
{
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
gData.gnssInterface->gnssNiResponse(this, id, response);
} else {
LOC_LOGE("%s:%d]: No gnss interface available for Location API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
}
void LocationAPI::enableNetworkProvider() {
void* libHandle = nullptr;
enableProviderGetter* setter = (enableProviderGetter*)dlGetSymFromLib(libHandle,
"liblocationservice_glue.so", "enableNetworkProvider");
if (setter != nullptr) {
(*setter)();
} else {
LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
}
}
void LocationAPI::disableNetworkProvider() {
void* libHandle = nullptr;
disableProviderGetter* setter = (disableProviderGetter*)dlGetSymFromLib(libHandle,
"liblocationservice_glue.so", "disableNetworkProvider");
if (setter != nullptr) {
(*setter)();
} else {
LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
}
}
void LocationAPI::startNetworkLocation(trackingCallback* callback) {
void* libHandle = nullptr;
getSingleNetworkLocationGetter* setter =
(getSingleNetworkLocationGetter*)dlGetSymFromLib(libHandle,
"liblocationservice_glue.so", "startNetworkLocation");
if (setter != nullptr) {
(*setter)(callback);
} else {
LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
}
}
void LocationAPI::stopNetworkLocation(trackingCallback* callback) {
void* libHandle = nullptr;
stopNetworkLocationGetter* setter = (stopNetworkLocationGetter*)dlGetSymFromLib(libHandle,
"liblocationservice_glue.so", "stopNetworkLocation");
if (setter != nullptr) {
LOC_LOGe("called");
(*setter)(callback);
} else {
LOC_LOGe("dlGetSymFromLib failed for liblocationservice_glue.so");
}
}
LocationControlAPI*
LocationControlAPI::createInstance(LocationControlCallbacks& locationControlCallbacks)
{
LocationControlAPI* controlAPI = NULL;
pthread_mutex_lock(&gDataMutex);
if (NULL != gData.controlAPI) {
controlAPI = gData.controlAPI;
} else {
if (nullptr != locationControlCallbacks.responseCb && NULL == gData.controlAPI) {
loadLibGnss();
if (NULL != gData.gnssInterface) {
gData.controlAPI = new LocationControlAPI();
gData.controlCallbacks = locationControlCallbacks;
gData.gnssInterface->setControlCallbacks(locationControlCallbacks);
controlAPI = gData.controlAPI;
}
}
}
pthread_mutex_unlock(&gDataMutex);
return controlAPI;
}
LocationControlAPI*
LocationControlAPI::getInstance()
{
LocationControlAPI* controlAPI = NULL;
pthread_mutex_lock(&gDataMutex);
controlAPI = gData.controlAPI;
pthread_mutex_unlock(&gDataMutex);
return controlAPI;
}
void
LocationControlAPI::destroy()
{
delete this;
}
LocationControlAPI::LocationControlAPI()
{
LOC_LOGD("LOCATION CONTROL API CONSTRUCTOR");
}
LocationControlAPI::~LocationControlAPI()
{
LOC_LOGD("LOCATION CONTROL API DESTRUCTOR");
pthread_mutex_lock(&gDataMutex);
gData.controlAPI = NULL;
pthread_mutex_unlock(&gDataMutex);
}
uint32_t
LocationControlAPI::enable(LocationTechnologyType techType)
{
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->enable(techType);
} else {
LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
void
LocationControlAPI::disable(uint32_t id)
{
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
gData.gnssInterface->disable(id);
} else {
LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
}
uint32_t*
LocationControlAPI::gnssUpdateConfig(const GnssConfig& config)
{
uint32_t* ids = NULL;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
ids = gData.gnssInterface->gnssUpdateConfig(config);
} else {
LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
return ids;
}
uint32_t* LocationControlAPI::gnssGetConfig(GnssConfigFlagsMask mask) {
uint32_t* ids = NULL;
pthread_mutex_lock(&gDataMutex);
if (NULL != gData.gnssInterface) {
ids = gData.gnssInterface->gnssGetConfig(mask);
} else {
LOC_LOGe("No gnss interface available for Control API client %p", this);
}
pthread_mutex_unlock(&gDataMutex);
return ids;
}
uint32_t
LocationControlAPI::gnssDeleteAidingData(GnssAidingData& data)
{
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->gnssDeleteAidingData(data);
} else {
LOC_LOGE("%s:%d]: No gnss interface available for Location Control API client %p ",
__func__, __LINE__, this);
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
uint32_t LocationControlAPI::configConstellations(
const GnssSvTypeConfig& constellationEnablementConfig,
const GnssSvIdConfig& blacklistSvConfig) {
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->gnssUpdateSvConfig(
constellationEnablementConfig, blacklistSvConfig);
} else {
LOC_LOGe("No gnss interface available for Location Control API");
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
uint32_t LocationControlAPI::configConstellationSecondaryBand(
const GnssSvTypeConfig& secondaryBandConfig) {
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->gnssUpdateSecondaryBandConfig(secondaryBandConfig);
} else {
LOC_LOGe("No gnss interface available for Location Control API");
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
uint32_t LocationControlAPI::configConstrainedTimeUncertainty(
bool enable, float tuncThreshold, uint32_t energyBudget) {
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->setConstrainedTunc(enable,
tuncThreshold,
energyBudget);
} else {
LOC_LOGe("No gnss interface available for Location Control API");
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
uint32_t LocationControlAPI::configPositionAssistedClockEstimator(bool enable) {
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->setPositionAssistedClockEstimator(enable);
} else {
LOC_LOGe("No gnss interface available for Location Control API");
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
uint32_t LocationControlAPI::configLeverArm(const LeverArmConfigInfo& configInfo) {
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->configLeverArm(configInfo);
} else {
LOC_LOGe("No gnss interface available for Location Control API");
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
uint32_t LocationControlAPI::configRobustLocation(bool enable, bool enableForE911) {
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->configRobustLocation(enable, enableForE911);
} else {
LOC_LOGe("No gnss interface available for Location Control API");
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
uint32_t LocationControlAPI::configMinGpsWeek(uint16_t minGpsWeek) {
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->configMinGpsWeek(minGpsWeek);
} else {
LOC_LOGe("No gnss interface available for Location Control API");
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
uint32_t LocationControlAPI::configDeadReckoningEngineParams(
const DeadReckoningEngineConfig& dreConfig) {
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->configDeadReckoningEngineParams(dreConfig);
} else {
LOC_LOGe("No gnss interface available for Location Control API");
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
uint32_t LocationControlAPI::configEngineRunState(
PositioningEngineMask engType, LocEngineRunState engState) {
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->configEngineRunState(engType, engState);
} else {
LOC_LOGe("No gnss interface available for Location Control API");
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
uint32_t LocationControlAPI::setOptInStatus(bool userConsent) {
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->setOptInStatus(userConsent);
} else {
LOC_LOGe("No gnss interface available for Location Control API");
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
uint32_t LocationControlAPI::configOutputNmeaTypes(
GnssNmeaTypesMask enabledNmeaTypes) {
uint32_t id = 0;
pthread_mutex_lock(&gDataMutex);
if (gData.gnssInterface != NULL) {
id = gData.gnssInterface->configOutputNmeaTypes(enabledNmeaTypes);
} else {
LOC_LOGe("No gnss interface available for Location Control API");
}
pthread_mutex_unlock(&gDataMutex);
return id;
}
void LocationControlAPI::powerStateEvent(PowerStateType powerState) {
pthread_mutex_lock(&gDataMutex);
LOC_LOGv("--> entry, powerState: %d", powerState);
if (NULL != gData.gnssInterface) {
gData.gnssInterface->updateSystemPowerState(powerState);
} else {
LOC_LOGv("No gnss interface available.");
}
if (NULL != gData.geofenceInterface) {
gData.geofenceInterface->updateSystemPowerState(powerState);
} else {
LOC_LOGv("No geofence interface available.");
}
if (NULL != gData.batchingInterface) {
gData.batchingInterface->updateSystemPowerState(powerState);
} else {
LOC_LOGv("No batching interface available.");
}
pthread_mutex_unlock(&gDataMutex);
}

561
gps/location/LocationAPI.h Normal file
View File

@@ -0,0 +1,561 @@
/* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LOCATIONAPI_H
#define LOCATIONAPI_H
#include "ILocationAPI.h"
class LocationAPI : public ILocationAPI
{
private:
LocationAPI();
~LocationAPI();
public:
/* creates an instance to LocationAPI object.
Will return NULL if mandatory parameters are invalid or if the maximum number
of instances have been reached */
static LocationAPI* createInstance(LocationCallbacks&);
/* destroy/cleans up the instance, which should be called when LocationControlAPI object is
no longer needed. LocationControlAPI* returned from createInstance will no longer valid
after destroy is called.
If the caller allocates the memory for LocationControlCallbacks used in
LocationControlAPI::createInstance, then the caller must ensure that the memory still remains
valid until destroyCompleteCb is invoked.
*/
void destroy(locationApiDestroyCompleteCallback destroyCompleteCb=nullptr);
void onRemoveClientCompleteCb (LocationAdapterTypeMask adapterType);
/* updates/changes the callbacks that will be called.
mandatory callbacks must be present for callbacks to be successfully updated
no return value */
virtual void updateCallbacks(LocationCallbacks&) override;
/* ================================== TRACKING ================================== */
/* startTracking starts a tracking session, which returns a session id that will be
used by the other tracking APIs and also in the responseCallback to match command
with response. locations are reported on the trackingCallback passed in createInstance
periodically according to LocationOptions.
responseCallback returns:
LOCATION_ERROR_SUCCESS if session was successfully started
LOCATION_ERROR_ALREADY_STARTED if a startTracking session is already in progress
LOCATION_ERROR_CALLBACK_MISSING if no trackingCallback was passed in createInstance
LOCATION_ERROR_INVALID_PARAMETER if TrackingOptions parameter is invalid */
virtual uint32_t startTracking(TrackingOptions&) override;
/* stopTracking stops a tracking session associated with id parameter.
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */
virtual void stopTracking(uint32_t id) override;
/* updateTrackingOptions changes the TrackingOptions of a tracking session associated with id
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if TrackingOptions parameters are invalid
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a tracking session */
virtual void updateTrackingOptions(uint32_t id, TrackingOptions&) override;
/* ================================== BATCHING ================================== */
/* startBatching starts a batching session, which returns a session id that will be
used by the other batching APIs and also in the responseCallback to match command
with response. locations are reported on the batchingCallback passed in createInstance
periodically according to LocationOptions. A batching session starts tracking on
the low power processor and delivers them in batches by the batchingCallback when
the batch is full or when getBatchedLocations is called. This allows for the processor
that calls this API to sleep when the low power processor can batch locations in the
backgroup and wake up the processor calling the API only when the batch is full, thus
saving power
responseCallback returns:
LOCATION_ERROR_SUCCESS if session was successful
LOCATION_ERROR_ALREADY_STARTED if a startBatching session is already in progress
LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback was passed in createInstance
LOCATION_ERROR_INVALID_PARAMETER if a parameter is invalid
LOCATION_ERROR_NOT_SUPPORTED if batching is not supported */
virtual uint32_t startBatching(BatchingOptions&) override;
/* stopBatching stops a batching session associated with id parameter.
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id is not associated with batching session */
virtual void stopBatching(uint32_t id) override;
/* updateBatchingOptions changes the BatchingOptions of a batching session associated with id
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if BatchingOptions parameters are invalid
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */
virtual void updateBatchingOptions(uint32_t id, BatchingOptions&) override;
/* getBatchedLocations gets a number of locations that are currently stored/batched
on the low power processor, delivered by the batchingCallback passed in createInstance.
Location are then deleted from the batch stored on the low power processor.
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful, will be followed by batchingCallback call
LOCATION_ERROR_CALLBACK_MISSING if no batchingCallback was passed in createInstance
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a batching session */
virtual void getBatchedLocations(uint32_t id, size_t count) override;
/* ================================== GEOFENCE ================================== */
/* addGeofences adds any number of geofences and returns an array of geofence ids that
will be used by the other geofence APIs and also in the collectiveResponseCallback to
match command with response. The geofenceBreachCallback will deliver the status of each
geofence according to the GeofenceOption for each. The geofence id array returned will
be valid until the collectiveResponseCallback is called and has returned.
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if session was successful
LOCATION_ERROR_CALLBACK_MISSING if no geofenceBreachCallback
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
LOCATION_ERROR_NOT_SUPPORTED if geofence is not supported */
virtual uint32_t* addGeofences(size_t count, GeofenceOption*, GeofenceInfo*) override;
/* removeGeofences removes any number of geofences. Caller should delete ids array after
removeGeofences returneds.
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */
virtual void removeGeofences(size_t count, uint32_t* ids) override;
/* modifyGeofences modifies any number of geofences. Caller should delete ids array after
modifyGeofences returns.
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid */
virtual void modifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options) override;
/* pauseGeofences pauses any number of geofences, which is similar to removeGeofences,
only that they can be resumed at any time. Caller should delete ids array after
pauseGeofences returns.
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */
virtual void pauseGeofences(size_t count, uint32_t* ids) override;
/* resumeGeofences resumes any number of geofences that are currently paused. Caller should
delete ids array after resumeGeofences returns.
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id is not associated with a geofence session */
virtual void resumeGeofences(size_t count, uint32_t* ids) override;
/* ================================== GNSS ====================================== */
/* gnssNiResponse is called in response to a gnssNiCallback.
responseCallback returns:
LOCATION_ERROR_SUCCESS if session was successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters in GnssNiResponse are invalid
LOCATION_ERROR_ID_UNKNOWN if id does not match a gnssNiCallback */
virtual void gnssNiResponse(uint32_t id, GnssNiResponse response) override;
/* ================================== NETWORK PROVIDER =========================== */
/* enableNetworkProvider enables Network Provider */
virtual void enableNetworkProvider();
/* disableNetworkProvider disables Network Provider */
virtual void disableNetworkProvider();
/* startNetworkLocation starts tracking session for
network location request */
virtual void startNetworkLocation(trackingCallback* callback);
/* stopNetworkLocation stops the ongoing tracking session for
network location request */
virtual void stopNetworkLocation(trackingCallback* callback);
};
typedef struct {
size_t size; // set to sizeof(LocationControlCallbacks)
responseCallback responseCb; // mandatory
collectiveResponseCallback collectiveResponseCb; // mandatory
gnssConfigCallback gnssConfigCb; // optional
} LocationControlCallbacks;
class LocationControlAPI : public ILocationControlAPI
{
private:
LocationControlAPI();
~LocationControlAPI();
public:
/* creates an instance to LocationControlAPI object.
Will return NULL if mandatory parameters are invalid or if the maximum number
of instances have been reached. Only once instance allowed */
static LocationControlAPI* createInstance(LocationControlCallbacks&);
static LocationControlAPI* getInstance();
/* destroy/cleans up the instance, which should be called when LocationControlAPI object is
no longer needed. LocationControlAPI* returned from createInstance will no longer valid
after destroy is called */
void destroy();
/* enable will enable specific location technology to be used for calculation locations and
will effectively start a control session if call is successful, which returns a session id
that will be returned in responseCallback to match command with response. The session id is
also needed to call the disable command.
This effect is global for all clients of LocationAPI
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ALREADY_STARTED if an enable was already called for this techType
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */
uint32_t enable(LocationTechnologyType techType);
/* disable will disable specific location technology to be used for calculation locations and
effectively ends the control session if call is successful.
id parameter is the session id that was returned in enable responseCallback for techType.
The session id is no longer valid after disable's responseCallback returns success.
This effect is global for all clients of LocationAPI
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_ID_UNKNOWN if id was not returned from responseCallback from enable
LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason */
void disable(uint32_t id);
/* gnssUpdateConfig updates the gnss specific configuration, which returns a session id array
with an id for each of the bits set in GnssConfig.flags, order from low bits to high bits.
The response for each config that is set will be returned in collectiveResponseCallback.
The session id array returned will be valid until the collectiveResponseCallback is called
and has returned. This effect is global for all clients of LocationAPI
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if session was successful
LOCATION_ERROR_INVALID_PARAMETER if any other parameters are invalid
LOCATION_ERROR_GENERAL_FAILURE if failure for any other reason
PLEASE NOTE: It is caller's resposibility to FREE the memory of the return value.
The memory must be freed by delete [].*/
virtual uint32_t* gnssUpdateConfig(const GnssConfig& config) override;
/* gnssGetConfig fetches the current constellation and SV configuration
on the GNSS engine.
Returns a session id array with an id for each of the bits set in
the mask parameter, order from low bits to high bits.
Response is sent via the registered gnssConfigCallback.
This effect is global for all clients of LocationAPI
collectiveResponseCallback returns:
LOCATION_ERROR_SUCCESS if session was successful
LOCATION_ERROR_INVALID_PARAMETER if any parameter is invalid
LOCATION_ERROR_CALLBACK_MISSING If no gnssConfigCallback
was passed in createInstance
LOCATION_ERROR_NOT_SUPPORTED If read of requested configuration
is not supported
PLEASE NOTE: It is caller's resposibility to FREE the memory of the return value.
The memory must be freed by delete [].*/
uint32_t* gnssGetConfig(GnssConfigFlagsMask mask);
/* delete specific gnss aiding data for testing, which returns a session id
that will be returned in responseCallback to match command with response.
Only allowed in userdebug builds. This effect is global for all clients of LocationAPI
responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
LOCATION_ERROR_NOT_SUPPORTED if build is not userdebug */
virtual uint32_t gnssDeleteAidingData(GnssAidingData& data) override;
/** @brief
Configure the constellation and SVs to be used by the GNSS engine on
modem.
@param
constellationEnablementConfig: configuration to enable/disable SV
constellation to be used by SPE engine. When size in
constellationEnablementConfig is set to 0, this indicates to reset SV
constellation configuration to modem NV default.
blacklistSvConfig: configuration to blacklist or unblacklist SVs
used by SPE engine
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configConstellations(
const GnssSvTypeConfig& constellationEnablementConfig,
const GnssSvIdConfig& blacklistSvConfig) override;
/** @brief
Configure the secondary band of constellations to be used by
the GNSS engine on modem.
@param
secondaryBandConfig: configuration the secondary band usage
for SPE engine
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configConstellationSecondaryBand(
const GnssSvTypeConfig& secondaryBandConfig) override;
/** @brief
Enable or disable the constrained time uncertainty feature.
@param
enable: true to enable the constrained time uncertainty
feature and false to disable the constrainted time
uncertainty feature.
@param
tuncThreshold: this specifies the time uncertainty threshold
that gps engine need to maintain, in units of milli-seconds.
Default is 0.0 meaning that modem default value of time
uncertainty threshold will be used. This parameter is
ignored when requesting to disable this feature.
@param
energyBudget: this specifies the power budget that gps
engine is allowed to spend to maintain the time uncertainty.
Default is 0 meaning that GPS engine is not constained by
power budget and can spend as much power as needed. The
parameter need to be specified in units of 0.1 milli watt
second. This parameter is ignored requesting to disable this
feature.
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters
are invalid
*/
virtual uint32_t configConstrainedTimeUncertainty(
bool enable, float tuncThreshold = 0.0,
uint32_t energyBudget = 0) override;
/** @brief
Enable or disable position assisted clock estimator feature.
@param
enable: true to enable position assisted clock estimator and
false to disable the position assisted clock estimator
feature.
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configPositionAssistedClockEstimator(bool enable) override;
/** @brief
Sets the lever arm parameters for the vehicle.
@param
configInfo: lever arm configuration info regarding below two
types of lever arm info:
a: GNSS Antenna w.r.t the origin at the IMU e.g.: inertial
measurement unit.
b: lever arm parameters regarding the OPF (output frame)
w.r.t the origin (at the GPS Antenna). Vehicle manufacturers
prefer the position output to be tied to a specific point in
the vehicle rather than where the antenna is placed
(midpoint of the rear axle is typical).
Caller can choose types of lever arm info to configure via the
leverMarkTypeMask.
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configLeverArm(const LeverArmConfigInfo& configInfo) override;
/** @brief
Configure the robust location setting.
@param
enable: true to enable robust location and false to disable
robust location.
@param
enableForE911: true to enable robust location when device is
on E911 session and false to disable on E911 session.
This parameter is only valid if robust location is enabled.
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configRobustLocation(bool enable, bool enableForE911) override;
/** @brief
Config the minimal GPS week used by modem GNSS engine.
@param
minGpsWeek: minimal GPS week to be used by modem GNSS engine.
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configMinGpsWeek(uint16_t minGpsWeek) override;
/** @brief
Configure the vehicle body-to-Sensor mount parameters and
other parameters for dead reckoning position engine.
@param
dreConfig: vehicle body-to-Sensor mount angles and other
parameters.
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configDeadReckoningEngineParams(
const DeadReckoningEngineConfig& dreConfig) override;
/** @brief
This API is used to instruct the specified engine to be in
the pause/resume state. <br/>
When the engine is placed in paused state, the engine will
stop. If there is an on-going session, engine will no longer
produce fixes. In the paused state, calling API to delete
aiding data from the paused engine may not have effect.
Request to delete Aiding data shall be issued after
engine resume. <br/>
Currently, only DRE engine will support pause/resume
request. responseCb() will return not supported when request
is made to pause/resume none-DRE engine. <br/>
Request to pause/resume DRE engine can be made with or
without an on-going session. With QDR engine, on resume, GNSS
position & heading re-acquisition is needed for DR engine to
engage. If DR engine is already in the requested state, the
request will be no-op. <br/>
@param
engType: the engine that is instructed to change its run
state. <br/>
engState: the new engine run state that the engine is
instructed to be in. <br/>
@return
A session id that will be returned in responseCallback to
match command with response. This effect is global for all
clients of LocationAPI responseCallback returns:
LOCATION_ERROR_SUCCESS if successful
LOCATION_ERROR_INVALID_PARAMETER if any parameters are invalid
*/
virtual uint32_t configEngineRunState(PositioningEngineMask engType,
LocEngineRunState engState) override;
/** @brief
Set the EULA opt-in status from system user. This is used as consent to
use network-based positioning.
@param
userConsnt: user agrees to use GTP service or not.
@return
A session id that will be returned in responseCallback to
match command with response.
*/
virtual uint32_t setOptInStatus(bool userConsent);
/** @brief
This API is used to config the NMEA sentence types.
Without prior calling this API, all NMEA sentences supported
in the system, as defined in NmeaTypesMask, will get
generated and delivered to all the location clients that
register to receive NMEA sentences.
The NMEA sentence types are per-device setting and calling
this API will impact all the location api clients that
register to receive NMEA sentences. This API call is not
incremental and the new NMEA sentence types will completely
overwrite the previous call.
If one or more unspecified bits are set in the NMEA mask,
those bits will be ignored, but the rest of the
configuration will get applied.
Please note that the configured NMEA sentence types are not
persistent.
@param
enabledNmeaTypes: specify the set of NMEA sentences the
device will generate and deliver to the location api clients
that register to receive NMEA sentences. <br/>
@return
A session id that will be returned in responseCallback to
match command with response.
*/
virtual uint32_t configOutputNmeaTypes(
GnssNmeaTypesMask enabledNmeaTypes) override;
/** @brief
This API is used to send platform power events to GNSS adapters in order
to handle GNSS sessions as per platform power event.
@param
powerState: Current vehicle/platform power state.
@return
No return value.
*/
virtual void powerStateEvent(PowerStateType powerState) override;
};
#endif /* LOCATIONAPI_H */

View File

@@ -0,0 +1,969 @@
/* Copyright (c) 2017, 2020-2021 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define LOG_NDEBUG 0
#define LOG_TAG "LocSvc_APIClientBase"
#include <loc_pla.h>
#include <log_util.h>
#include <inttypes.h>
#include <loc_cfg.h>
#include "LocationAPIClientBase.h"
#define GEOFENCE_SESSION_ID 0xFFFFFFFF
#define CONFIG_SESSION_ID 0xFFFFFFFF
// LocationAPIControlClient
LocationAPIControlClient::LocationAPIControlClient() :
mEnabled(false)
{
pthread_mutex_init(&mMutex, nullptr);
for (int i = 0; i < CTRL_REQUEST_MAX; i++) {
mRequestQueues[i].reset((uint32_t)0);
}
LocationControlCallbacks locationControlCallbacks;
locationControlCallbacks.size = sizeof(LocationControlCallbacks);
locationControlCallbacks.responseCb =
[this](LocationError error, uint32_t id) {
onCtrlResponseCb(error, id);
};
locationControlCallbacks.collectiveResponseCb =
[this](size_t count, LocationError* errors, uint32_t* ids) {
onCtrlCollectiveResponseCb(count, errors, ids);
};
mLocationControlAPI = LocationControlAPI::createInstance(locationControlCallbacks);
}
LocationAPIControlClient::~LocationAPIControlClient()
{
pthread_mutex_lock(&mMutex);
if (mLocationControlAPI) {
mLocationControlAPI->destroy();
mLocationControlAPI = nullptr;
}
for (int i = 0; i < CTRL_REQUEST_MAX; i++) {
mRequestQueues[i].reset((uint32_t)0);
}
pthread_mutex_unlock(&mMutex);
pthread_mutex_destroy(&mMutex);
}
uint32_t LocationAPIControlClient::locAPIGnssDeleteAidingData(GnssAidingData& data)
{
uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
pthread_mutex_lock(&mMutex);
if (mLocationControlAPI) {
uint32_t session = mLocationControlAPI->gnssDeleteAidingData(data);
LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].reset(session);
mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].push(new GnssDeleteAidingDataRequest(*this));
retVal = LOCATION_ERROR_SUCCESS;
}
pthread_mutex_unlock(&mMutex);
return retVal;
}
uint32_t LocationAPIControlClient::locAPIEnable(LocationTechnologyType techType)
{
uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
pthread_mutex_lock(&mMutex);
if (mEnabled) {
// just return success if already enabled
retVal = LOCATION_ERROR_SUCCESS;
} else if (mLocationControlAPI) {
uint32_t session = mLocationControlAPI->enable(techType);
LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
mRequestQueues[CTRL_REQUEST_CONTROL].reset(session);
mRequestQueues[CTRL_REQUEST_CONTROL].push(new EnableRequest(*this));
retVal = LOCATION_ERROR_SUCCESS;
mEnabled = true;
} else {
LOC_LOGE("%s:%d] failed.", __FUNCTION__, __LINE__);
}
pthread_mutex_unlock(&mMutex);
return retVal;
}
void LocationAPIControlClient::locAPIDisable()
{
pthread_mutex_lock(&mMutex);
if (mEnabled && mLocationControlAPI) {
uint32_t session = 0;
session = mRequestQueues[CTRL_REQUEST_CONTROL].getSession();
if (session > 0) {
mRequestQueues[CTRL_REQUEST_CONTROL].push(new DisableRequest(*this));
mLocationControlAPI->disable(session);
mEnabled = false;
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
}
}
pthread_mutex_unlock(&mMutex);
}
uint32_t LocationAPIControlClient::locAPIGnssUpdateConfig(GnssConfig config)
{
uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
pthread_mutex_lock(&mMutex);
if (mLocationControlAPI) {
uint32_t* idArray = mLocationControlAPI->gnssUpdateConfig(config);
LOC_LOGv("gnssUpdateConfig return array: %p", idArray);
if (nullptr != idArray) {
if (nullptr != mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].getSessionArrayPtr()) {
mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].reset(idArray);
}
mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].push(new GnssUpdateConfigRequest(*this));
retVal = LOCATION_ERROR_SUCCESS;
delete [] idArray;
}
}
pthread_mutex_unlock(&mMutex);
return retVal;
}
uint32_t LocationAPIControlClient::locAPIGnssGetConfig(GnssConfigFlagsMask mask)
{
uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
pthread_mutex_lock(&mMutex);
if (mLocationControlAPI) {
uint32_t* idArray = mLocationControlAPI->gnssGetConfig(mask);
LOC_LOGv("gnssGetConfig return array: %p", idArray);
if (nullptr != idArray) {
if (nullptr != mRequestQueues[CTRL_REQUEST_CONFIG_GET].getSessionArrayPtr()) {
mRequestQueues[CTRL_REQUEST_CONFIG_GET].reset(idArray);
}
mRequestQueues[CTRL_REQUEST_CONFIG_GET].push(new GnssGetConfigRequest(*this));
retVal = LOCATION_ERROR_SUCCESS;
delete [] idArray;
}
}
pthread_mutex_unlock(&mMutex);
return retVal;
}
void LocationAPIControlClient::onCtrlResponseCb(LocationError error, uint32_t id)
{
if (error != LOCATION_ERROR_SUCCESS) {
LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, error, id);
} else {
LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, error, id);
}
LocationAPIRequest* request = getRequestBySession(id);
if (request) {
request->onResponse(error, id);
delete request;
}
}
void LocationAPIControlClient::onCtrlCollectiveResponseCb(
size_t count, LocationError* errors, uint32_t* ids)
{
for (size_t i = 0; i < count; i++) {
if (errors[i] != LOCATION_ERROR_SUCCESS) {
LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
} else {
LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
}
}
LocationAPIRequest* request = getRequestBySessionArrayPtr(ids);
if (request) {
request->onCollectiveResponse(count, errors, ids);
delete request;
}
}
LocationAPIRequest* LocationAPIControlClient::getRequestBySession(uint32_t session)
{
pthread_mutex_lock(&mMutex);
LocationAPIRequest* request = nullptr;
if (mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].getSession() == session) {
request = mRequestQueues[CTRL_REQUEST_DELETEAIDINGDATA].pop();
} else if (mRequestQueues[CTRL_REQUEST_CONTROL].getSession() == session) {
request = mRequestQueues[CTRL_REQUEST_CONTROL].pop();
}
pthread_mutex_unlock(&mMutex);
return request;
}
LocationAPIRequest*
LocationAPIControlClient::getRequestBySessionArrayPtr(
uint32_t* sessionArrayPtr)
{
pthread_mutex_lock(&mMutex);
LocationAPIRequest* request = nullptr;
if (mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].getSessionArrayPtr() == sessionArrayPtr) {
request = mRequestQueues[CTRL_REQUEST_CONFIG_UPDATE].pop();
} else if (mRequestQueues[CTRL_REQUEST_CONFIG_GET].getSessionArrayPtr() == sessionArrayPtr) {
request = mRequestQueues[CTRL_REQUEST_CONFIG_GET].pop();
}
pthread_mutex_unlock(&mMutex);
return request;
}
// LocationAPIClientBase
LocationAPIClientBase::LocationAPIClientBase() :
mGeofenceBreachCallback(nullptr),
mBatchingStatusCallback(nullptr),
mLocationAPI(nullptr),
mBatchSize(-1),
mTracking(false)
{
// use recursive mutex, in case callback come from the same thread
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mMutex, &attr);
for (int i = 0; i < REQUEST_MAX; i++) {
mRequestQueues[i].reset((uint32_t)0);
}
}
void LocationAPIClientBase::locAPISetCallbacks(LocationCallbacks& locationCallbacks)
{
pthread_mutex_lock(&mMutex);
if (locationCallbacks.geofenceBreachCb != nullptr) {
mGeofenceBreachCallback = locationCallbacks.geofenceBreachCb;
locationCallbacks.geofenceBreachCb =
[this](GeofenceBreachNotification geofenceBreachNotification) {
beforeGeofenceBreachCb(geofenceBreachNotification);
};
}
locationCallbacks.capabilitiesCb =
[this](LocationCapabilitiesMask capabilitiesMask) {
onCapabilitiesCb(capabilitiesMask);
};
locationCallbacks.responseCb = [this](LocationError error, uint32_t id) {
onResponseCb(error, id);
};
locationCallbacks.collectiveResponseCb =
[this](size_t count, LocationError* errors, uint32_t* ids) {
onCollectiveResponseCb(count, errors, ids);
};
if (locationCallbacks.batchingStatusCb != nullptr) {
mBatchingStatusCallback = locationCallbacks.batchingStatusCb;
locationCallbacks.batchingStatusCb =
[this](BatchingStatusInfo batchStatus, std::list<uint32_t> & tripCompletedList) {
beforeBatchingStatusCb(batchStatus, tripCompletedList);
};
}
if (mLocationAPI == nullptr ) {
mLocationAPI = LocationAPI::createInstance(locationCallbacks);
} else {
mLocationAPI->updateCallbacks(locationCallbacks);
}
pthread_mutex_unlock(&mMutex);
}
void LocationAPIClientBase::destroy()
{
LOC_LOGD("LocationAPIClientBase::destroy()");
pthread_mutex_lock(&mMutex);
mGeofenceBreachCallback = nullptr;
for (int i = 0; i < REQUEST_MAX; i++) {
mRequestQueues[i].reset((uint32_t)0);
}
LocationAPI* localHandle = nullptr;
if (nullptr != mLocationAPI) {
localHandle = mLocationAPI;
mLocationAPI = nullptr;
}
pthread_mutex_unlock(&mMutex);
// Invoking destroy has the possibility of destroy complete callback
// being invoked right away in the same context, hence no instance
// member must be accessed after the destroy call.
if (nullptr != localHandle) {
localHandle->destroy([this]() {onLocationApiDestroyCompleteCb();});
}
}
LocationAPIClientBase::~LocationAPIClientBase()
{
pthread_mutex_destroy(&mMutex);
}
void LocationAPIClientBase::onLocationApiDestroyCompleteCb()
{
LOC_LOGD("LocationAPIClientBase::onLocationApiDestroyCompleteCb()");
delete this;
}
uint32_t LocationAPIClientBase::locAPIStartTracking(TrackingOptions& options)
{
uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
if (mTracking) {
LOC_LOGW("%s:%d] Existing tracking session present", __FUNCTION__, __LINE__);
} else {
uint32_t session = mLocationAPI->startTracking(options);
LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
// onResponseCb might be called from other thread immediately after
// startTracking returns, so we are not going to unlock mutex
// until StartTrackingRequest is pushed into mRequestQueues[REQUEST_TRACKING]
mRequestQueues[REQUEST_TRACKING].reset(session);
mRequestQueues[REQUEST_TRACKING].push(new StartTrackingRequest(*this));
mTracking = true;
}
retVal = LOCATION_ERROR_SUCCESS;
}
pthread_mutex_unlock(&mMutex);
return retVal;
}
void LocationAPIClientBase::locAPIStopTracking()
{
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
uint32_t session = 0;
session = mRequestQueues[REQUEST_TRACKING].getSession();
if (session > 0) {
mRequestQueues[REQUEST_TRACKING].push(new StopTrackingRequest(*this));
mLocationAPI->stopTracking(session);
mTracking = false;
} else {
LOC_LOGD("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
}
}
pthread_mutex_unlock(&mMutex);
}
void LocationAPIClientBase::locAPIUpdateTrackingOptions(TrackingOptions& options)
{
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
uint32_t session = 0;
session = mRequestQueues[REQUEST_TRACKING].getSession();
if (session > 0) {
mRequestQueues[REQUEST_TRACKING].push(new UpdateTrackingOptionsRequest(*this));
mLocationAPI->updateTrackingOptions(session, options);
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__, session);
}
}
pthread_mutex_unlock(&mMutex);
}
int32_t LocationAPIClientBase::locAPIGetBatchSize()
{
if (mBatchSize == -1) {
const loc_param_s_type batching_conf_param_table[] =
{
{"BATCH_SIZE", &mBatchSize, nullptr, 'n'},
};
UTIL_READ_CONF(LOC_PATH_BATCHING_CONF, batching_conf_param_table);
if (mBatchSize < 0) {
// set mBatchSize to 0 if we got an illegal value from config file
mBatchSize = 0;
}
}
return mBatchSize;
}
uint32_t LocationAPIClientBase::locAPIStartSession(
uint32_t id, uint32_t sessionMode, TrackingOptions&& options)
{
uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
if (mSessionBiDict.hasId(id)) {
LOC_LOGE("%s:%d] session %d has already started.", __FUNCTION__, __LINE__, id);
retVal = LOCATION_ERROR_ALREADY_STARTED;
} else {
uint32_t trackingSession = 0;
uint32_t batchingSession = 0;
if (sessionMode == SESSION_MODE_ON_FIX) {
trackingSession = mLocationAPI->startTracking(options);
LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, trackingSession);
mRequestQueues[REQUEST_SESSION].push(new StartTrackingRequest(*this));
} else {
// Fill in the batch mode
BatchingOptions batchOptions = {};
batchOptions.size = sizeof(BatchingOptions);
switch (sessionMode) {
case SESSION_MODE_ON_FULL:
batchOptions.batchingMode = BATCHING_MODE_ROUTINE;
break;
case SESSION_MODE_ON_TRIP_COMPLETED:
batchOptions.batchingMode = BATCHING_MODE_TRIP;
break;
default:
batchOptions.batchingMode = BATCHING_MODE_NO_AUTO_REPORT;
break;
}
// Populate location option values
batchOptions.minDistance = options.minDistance;
batchOptions.minInterval = options.minInterval;
batchOptions.mode = options.mode;
batchingSession = mLocationAPI->startBatching(batchOptions);
LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, batchingSession);
mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
mRequestQueues[REQUEST_SESSION].push(new StartBatchingRequest(*this));
}
uint32_t session = ((sessionMode != SESSION_MODE_ON_FIX) ?
batchingSession : trackingSession);
SessionEntity entity;
entity.id = id;
entity.trackingSession = trackingSession;
entity.batchingSession = batchingSession;
entity.sessionMode = sessionMode;
mSessionBiDict.set(id, session, entity);
retVal = LOCATION_ERROR_SUCCESS;
}
}
pthread_mutex_unlock(&mMutex);
return retVal;
}
uint32_t LocationAPIClientBase::locAPIStopSession(uint32_t id)
{
uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
if (mSessionBiDict.hasId(id)) {
SessionEntity entity = mSessionBiDict.getExtById(id);
uint32_t trackingSession = entity.trackingSession;
uint32_t batchingSession = entity.batchingSession;
uint32_t sMode = entity.sessionMode;
if (sMode == SESSION_MODE_ON_FIX) {
mRequestQueues[REQUEST_SESSION].push(new StopTrackingRequest(*this));
mLocationAPI->stopTracking(trackingSession);
} else {
mRequestQueues[REQUEST_SESSION].push(new StopBatchingRequest(*this));
mLocationAPI->stopBatching(batchingSession);
}
retVal = LOCATION_ERROR_SUCCESS;
} else {
retVal = LOCATION_ERROR_ID_UNKNOWN;
LOC_LOGE("%s:%d] session %d is not exist.", __FUNCTION__, __LINE__, id);
}
}
pthread_mutex_unlock(&mMutex);
return retVal;
}
uint32_t LocationAPIClientBase::locAPIUpdateSessionOptions(
uint32_t id, uint32_t sessionMode, TrackingOptions&& options)
{
uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
if (mSessionBiDict.hasId(id)) {
SessionEntity entity = mSessionBiDict.getExtById(id);
uint32_t trackingSession = entity.trackingSession;
uint32_t batchingSession = entity.batchingSession;
uint32_t sMode = entity.sessionMode;
if (sessionMode == SESSION_MODE_ON_FIX) {
// we only add an UpdateTrackingOptionsRequest to mRequestQueues[REQUEST_SESSION],
// even if this update request will stop batching and then start tracking.
mRequestQueues[REQUEST_SESSION].push(new UpdateTrackingOptionsRequest(*this));
if (sMode == SESSION_MODE_ON_FIX) {
mLocationAPI->updateTrackingOptions(trackingSession, options);
} else {
// stop batching
// batchingSession will be removed from mSessionBiDict soon,
// so we don't need to add a new request to mRequestQueues[REQUEST_SESSION].
mLocationAPI->stopBatching(batchingSession);
batchingSession = 0;
mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
// start tracking
trackingSession = mLocationAPI->startTracking(options);
LOC_LOGI("%s:%d] start new session: %d",
__FUNCTION__, __LINE__, trackingSession);
}
} else {
// we only add an UpdateBatchingOptionsRequest to mRequestQueues[REQUEST_SESSION],
// even if this update request will stop tracking and then start batching.
mRequestQueues[REQUEST_SESSION].push(new UpdateBatchingOptionsRequest(*this));
BatchingOptions batchOptions = {};
batchOptions.size = sizeof(BatchingOptions);
switch (sessionMode) {
case SESSION_MODE_ON_FULL:
batchOptions.batchingMode = BATCHING_MODE_ROUTINE;
break;
case SESSION_MODE_ON_TRIP_COMPLETED:
batchOptions.batchingMode = BATCHING_MODE_TRIP;
break;
default:
batchOptions.batchingMode = BATCHING_MODE_NO_AUTO_REPORT;
break;
}
if (sMode == SESSION_MODE_ON_FIX) {
// stop tracking
// trackingSession will be removed from mSessionBiDict soon,
// so we don't need to add a new request to mRequestQueues[REQUEST_SESSION].
mLocationAPI->stopTracking(trackingSession);
trackingSession = 0;
// Populate location option values
batchOptions.minDistance = options.minDistance;
batchOptions.minInterval = options.minInterval;
batchOptions.mode = options.mode;
// start batching
batchingSession = mLocationAPI->startBatching(batchOptions);
LOC_LOGI("%s:%d] start new session: %d",
__FUNCTION__, __LINE__, batchingSession);
mRequestQueues[REQUEST_SESSION].setSession(batchingSession);
} else {
mLocationAPI->updateBatchingOptions(batchingSession, batchOptions);
}
}
uint32_t session = ((sessionMode != SESSION_MODE_ON_FIX) ?
batchingSession : trackingSession);
entity.trackingSession = trackingSession;
entity.batchingSession = batchingSession;
entity.sessionMode = sessionMode;
// remove the old values from mSessionBiDict before we add a new one.
mSessionBiDict.rmById(id);
mSessionBiDict.set(id, session, entity);
retVal = LOCATION_ERROR_SUCCESS;
} else {
retVal = LOCATION_ERROR_ID_UNKNOWN;
LOC_LOGE("%s:%d] session %d is not exist.", __FUNCTION__, __LINE__, id);
}
}
pthread_mutex_unlock(&mMutex);
return retVal;
}
uint32_t LocationAPIClientBase::locAPIGetBatchedLocations(uint32_t id, size_t count)
{
uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
if (mSessionBiDict.hasId(id)) {
SessionEntity entity = mSessionBiDict.getExtById(id);
if (entity.sessionMode != SESSION_MODE_ON_FIX) {
uint32_t batchingSession = entity.batchingSession;
mRequestQueues[REQUEST_SESSION].push(new GetBatchedLocationsRequest(*this));
mLocationAPI->getBatchedLocations(batchingSession, count);
retVal = LOCATION_ERROR_SUCCESS;
} else {
LOC_LOGE("%s:%d] Unsupported for session id: %d, mode is SESSION_MODE_ON_FIX",
__FUNCTION__, __LINE__, id);
retVal = LOCATION_ERROR_NOT_SUPPORTED;
}
} else {
retVal = LOCATION_ERROR_ID_UNKNOWN;
LOC_LOGd("unknown session id: %d, might flush() a stopped session", id);
}
}
pthread_mutex_unlock(&mMutex);
return retVal;
}
uint32_t LocationAPIClientBase::locAPIAddGeofences(
size_t count, uint32_t* ids, GeofenceOption* options, GeofenceInfo* data)
{
uint32_t retVal = LOCATION_ERROR_GENERAL_FAILURE;
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
if (mRequestQueues[REQUEST_GEOFENCE].getSession() != GEOFENCE_SESSION_ID) {
mRequestQueues[REQUEST_GEOFENCE].reset(GEOFENCE_SESSION_ID);
}
uint32_t* sessions = mLocationAPI->addGeofences(count, options, data);
if (sessions) {
LOC_LOGI("%s:%d] start new sessions: %p", __FUNCTION__, __LINE__, sessions);
mRequestQueues[REQUEST_GEOFENCE].push(new AddGeofencesRequest(*this));
for (size_t i = 0; i < count; i++) {
mGeofenceBiDict.set(ids[i], sessions[i], options[i].breachTypeMask);
}
retVal = LOCATION_ERROR_SUCCESS;
}
}
pthread_mutex_unlock(&mMutex);
return retVal;
}
void LocationAPIClientBase::locAPIRemoveGeofences(size_t count, uint32_t* ids)
{
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
if (sessions == NULL) {
LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
__FUNCTION__, __LINE__, sizeof(uint32_t) * count);
pthread_mutex_unlock(&mMutex);
return;
}
if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
BiDict<GeofenceBreachTypeMask>* removedGeofenceBiDict =
new BiDict<GeofenceBreachTypeMask>();
size_t j = 0;
for (size_t i = 0; i < count; i++) {
sessions[j] = mGeofenceBiDict.getSession(ids[i]);
if (sessions[j] > 0) {
GeofenceBreachTypeMask type = mGeofenceBiDict.getExtBySession(sessions[j]);
mGeofenceBiDict.rmBySession(sessions[j]);
removedGeofenceBiDict->set(ids[i], sessions[j], type);
j++;
}
}
if (j > 0) {
mRequestQueues[REQUEST_GEOFENCE].push(new RemoveGeofencesRequest(*this,
removedGeofenceBiDict));
mLocationAPI->removeGeofences(j, sessions);
} else {
delete(removedGeofenceBiDict);
}
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
mRequestQueues[REQUEST_GEOFENCE].getSession());
}
free(sessions);
}
pthread_mutex_unlock(&mMutex);
}
void LocationAPIClientBase::locAPIModifyGeofences(
size_t count, uint32_t* ids, GeofenceOption* options)
{
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
if (sessions == NULL) {
LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
__FUNCTION__, __LINE__, sizeof(uint32_t) * count);
pthread_mutex_unlock(&mMutex);
return;
}
if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
size_t j = 0;
for (size_t i = 0; i < count; i++) {
sessions[j] = mGeofenceBiDict.getSession(ids[i]);
if (sessions[j] > 0) {
mGeofenceBiDict.set(ids[i], sessions[j], options[i].breachTypeMask);
j++;
}
}
if (j > 0) {
mRequestQueues[REQUEST_GEOFENCE].push(new ModifyGeofencesRequest(*this));
mLocationAPI->modifyGeofences(j, sessions, options);
}
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
mRequestQueues[REQUEST_GEOFENCE].getSession());
}
free(sessions);
}
pthread_mutex_unlock(&mMutex);
}
void LocationAPIClientBase::locAPIPauseGeofences(size_t count, uint32_t* ids)
{
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
if (sessions == NULL) {
LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
__FUNCTION__, __LINE__, sizeof(uint32_t) * count);
pthread_mutex_unlock(&mMutex);
return;
}
if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
size_t j = 0;
for (size_t i = 0; i < count; i++) {
sessions[j] = mGeofenceBiDict.getSession(ids[i]);
if (sessions[j] > 0) {
j++;
}
}
if (j > 0) {
mRequestQueues[REQUEST_GEOFENCE].push(new PauseGeofencesRequest(*this));
mLocationAPI->pauseGeofences(j, sessions);
}
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
mRequestQueues[REQUEST_GEOFENCE].getSession());
}
free(sessions);
}
pthread_mutex_unlock(&mMutex);
}
void LocationAPIClientBase::locAPIResumeGeofences(
size_t count, uint32_t* ids, GeofenceBreachTypeMask* mask)
{
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
uint32_t* sessions = (uint32_t*)malloc(sizeof(uint32_t) * count);
if (sessions == NULL) {
LOC_LOGE("%s:%d] Failed to allocate %zu bytes !",
__FUNCTION__, __LINE__, sizeof(uint32_t) * count);
pthread_mutex_unlock(&mMutex);
return;
}
if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
size_t j = 0;
for (size_t i = 0; i < count; i++) {
sessions[j] = mGeofenceBiDict.getSession(ids[i]);
if (sessions[j] > 0) {
if (mask) {
mGeofenceBiDict.set(ids[i], sessions[j], mask[i]);
}
j++;
}
}
if (j > 0) {
mRequestQueues[REQUEST_GEOFENCE].push(new ResumeGeofencesRequest(*this));
mLocationAPI->resumeGeofences(j, sessions);
}
} else {
LOC_LOGE("%s:%d] invalid session: %d.", __FUNCTION__, __LINE__,
mRequestQueues[REQUEST_GEOFENCE].getSession());
}
free(sessions);
}
pthread_mutex_unlock(&mMutex);
}
void LocationAPIClientBase::locAPIRemoveAllGeofences()
{
std::vector<uint32_t> idsVec = mGeofenceBiDict.getAllIds();
if (idsVec.size() > 0) {
locAPIRemoveGeofences(idsVec.size(), &idsVec[0]);
}
}
void LocationAPIClientBase::locAPIGnssNiResponse(uint32_t id, GnssNiResponse response)
{
pthread_mutex_lock(&mMutex);
if (mLocationAPI) {
uint32_t session = id;
mLocationAPI->gnssNiResponse(id, response);
LOC_LOGI("%s:%d] start new session: %d", __FUNCTION__, __LINE__, session);
mRequestQueues[REQUEST_NIRESPONSE].reset(session);
mRequestQueues[REQUEST_NIRESPONSE].push(new GnssNiResponseRequest(*this));
}
pthread_mutex_unlock(&mMutex);
}
void LocationAPIClientBase::beforeGeofenceBreachCb(
GeofenceBreachNotification geofenceBreachNotification)
{
uint32_t* ids = (uint32_t*)malloc(sizeof(uint32_t) * geofenceBreachNotification.count);
uint32_t* backup = geofenceBreachNotification.ids;
size_t n = geofenceBreachNotification.count;
geofenceBreachCallback genfenceCallback = nullptr;
if (ids == NULL) {
LOC_LOGE("%s:%d] Failed to alloc %zu bytes",
__FUNCTION__, __LINE__,
sizeof(uint32_t) * geofenceBreachNotification.count);
return;
}
pthread_mutex_lock(&mMutex);
if (mGeofenceBreachCallback != nullptr) {
size_t count = 0;
for (size_t i = 0; i < n; i++) {
uint32_t id = mGeofenceBiDict.getId(geofenceBreachNotification.ids[i]);
GeofenceBreachTypeMask type =
mGeofenceBiDict.getExtBySession(geofenceBreachNotification.ids[i]);
// if type == 0, we will not head into the fllowing block anyway.
// so we don't need to check id and type
if ((geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER &&
(type & GEOFENCE_BREACH_ENTER_BIT)) ||
(geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT &&
(type & GEOFENCE_BREACH_EXIT_BIT))
) {
ids[count] = id;
count++;
}
}
geofenceBreachNotification.count = count;
geofenceBreachNotification.ids = ids;
genfenceCallback = mGeofenceBreachCallback;
}
pthread_mutex_unlock(&mMutex);
if (genfenceCallback != nullptr) {
genfenceCallback(geofenceBreachNotification);
}
// restore ids
geofenceBreachNotification.ids = backup;
geofenceBreachNotification.count = n;
free(ids);
}
void LocationAPIClientBase::beforeBatchingStatusCb(BatchingStatusInfo batchStatus,
std::list<uint32_t> & tripCompletedList) {
// map the trip ids to the client ids
std::list<uint32_t> tripCompletedClientIdList;
tripCompletedClientIdList.clear();
if (batchStatus.batchingStatus == BATCHING_STATUS_TRIP_COMPLETED) {
for (auto itt = tripCompletedList.begin(); itt != tripCompletedList.end(); itt++) {
if (mSessionBiDict.hasSession(*itt)) {
SessionEntity sessEntity = mSessionBiDict.getExtBySession(*itt);
if (sessEntity.sessionMode == SESSION_MODE_ON_TRIP_COMPLETED) {
tripCompletedClientIdList.push_back(sessEntity.id);
mSessionBiDict.rmBySession(*itt);
}
}
}
}
mBatchingStatusCallback(batchStatus, tripCompletedClientIdList);
}
void LocationAPIClientBase::onResponseCb(LocationError error, uint32_t id)
{
if (error != LOCATION_ERROR_SUCCESS) {
LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, error, id);
} else {
LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, error, id);
}
LocationAPIRequest* request = getRequestBySession(id);
if (request) {
request->onResponse(error, id);
delete request;
}
}
void LocationAPIClientBase::onCollectiveResponseCb(
size_t count, LocationError* errors, uint32_t* ids)
{
for (size_t i = 0; i < count; i++) {
if (errors[i] != LOCATION_ERROR_SUCCESS) {
LOC_LOGE("%s:%d] ERROR: %d ID: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
} else {
LOC_LOGV("%s:%d] SUCCESS: %d id: %d", __FUNCTION__, __LINE__, errors[i], ids[i]);
}
}
LocationAPIRequest* request = nullptr;
pthread_mutex_lock(&mMutex);
if (mRequestQueues[REQUEST_GEOFENCE].getSession() == GEOFENCE_SESSION_ID) {
request = mRequestQueues[REQUEST_GEOFENCE].pop();
}
pthread_mutex_unlock(&mMutex);
if (request) {
request->onCollectiveResponse(count, errors, ids);
delete request;
}
}
void LocationAPIClientBase::removeSession(uint32_t session) {
if (mSessionBiDict.hasSession(session)) {
mSessionBiDict.rmBySession(session);
}
}
LocationAPIRequest* LocationAPIClientBase::getRequestBySession(uint32_t session)
{
pthread_mutex_lock(&mMutex);
LocationAPIRequest* request = nullptr;
for (int i = 0; i < REQUEST_MAX; i++) {
if (i != REQUEST_GEOFENCE &&
i != REQUEST_SESSION &&
mRequestQueues[i].getSession() == session) {
request = mRequestQueues[i].pop();
break;
}
}
if (request == nullptr) {
// Can't find a request with correct session,
// try to find it from mSessionBiDict
if (mSessionBiDict.hasSession(session)) {
request = mRequestQueues[REQUEST_SESSION].pop();
}
}
pthread_mutex_unlock(&mMutex);
return request;
}

View File

@@ -0,0 +1,592 @@
/* Copyright (c) 2017,2020-2021 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LOCATION_API_CLINET_BASE_H
#define LOCATION_API_CLINET_BASE_H
#include <stdint.h>
#include <stdlib.h>
#include <pthread.h>
#include <queue>
#include <map>
#include "LocationAPI.h"
#include <loc_pla.h>
#include <log_util.h>
enum SESSION_MODE {
SESSION_MODE_NONE = 0,
SESSION_MODE_ON_FULL,
SESSION_MODE_ON_FIX,
SESSION_MODE_ON_TRIP_COMPLETED
};
enum REQUEST_TYPE {
REQUEST_TRACKING = 0,
REQUEST_SESSION,
REQUEST_GEOFENCE,
REQUEST_NIRESPONSE,
REQUEST_MAX,
};
enum CTRL_REQUEST_TYPE {
CTRL_REQUEST_DELETEAIDINGDATA = 0,
CTRL_REQUEST_CONTROL,
CTRL_REQUEST_CONFIG_UPDATE,
CTRL_REQUEST_CONFIG_GET,
CTRL_REQUEST_MAX,
};
class LocationAPIClientBase;
class LocationAPIRequest {
public:
LocationAPIRequest() {}
virtual ~LocationAPIRequest() {}
virtual void onResponse(LocationError /*error*/, uint32_t /*id*/) {}
virtual void onCollectiveResponse(
size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
};
class RequestQueue {
public:
RequestQueue(): mSession(0), mSessionArrayPtr(nullptr) {
}
virtual ~RequestQueue() {
reset((uint32_t)0);
}
void inline setSession(uint32_t session) { mSession = session; }
void inline setSessionArrayPtr(uint32_t* ptr) { mSessionArrayPtr = ptr; }
void reset(uint32_t session) {
LocationAPIRequest* request = nullptr;
while (!mQueue.empty()) {
request = mQueue.front();
mQueue.pop();
delete request;
}
mSession = session;
}
void reset(uint32_t* sessionArrayPtr) {
reset((uint32_t)0);
mSessionArrayPtr = sessionArrayPtr;
}
void push(LocationAPIRequest* request) {
mQueue.push(request);
}
LocationAPIRequest* pop() {
LocationAPIRequest* request = nullptr;
if (!mQueue.empty()) {
request = mQueue.front();
mQueue.pop();
}
return request;
}
uint32_t getSession() { return mSession; }
uint32_t* getSessionArrayPtr() { return mSessionArrayPtr; }
private:
uint32_t mSession;
uint32_t* mSessionArrayPtr;
std::queue<LocationAPIRequest*> mQueue;
};
class LocationAPIControlClient {
public:
LocationAPIControlClient();
virtual ~LocationAPIControlClient();
LocationAPIControlClient(const LocationAPIControlClient&) = delete;
LocationAPIControlClient& operator=(const LocationAPIControlClient&) = delete;
LocationAPIRequest* getRequestBySession(uint32_t session);
LocationAPIRequest* getRequestBySessionArrayPtr(uint32_t* sessionArrayPtr);
// LocationControlAPI
uint32_t locAPIGnssDeleteAidingData(GnssAidingData& data);
uint32_t locAPIEnable(LocationTechnologyType techType);
void locAPIDisable();
uint32_t locAPIGnssUpdateConfig(GnssConfig config);
uint32_t locAPIGnssGetConfig(GnssConfigFlagsMask config);
inline LocationControlAPI* getControlAPI() { return mLocationControlAPI; }
// callbacks
void onCtrlResponseCb(LocationError error, uint32_t id);
void onCtrlCollectiveResponseCb(size_t count, LocationError* errors, uint32_t* ids);
inline virtual void onGnssDeleteAidingDataCb(LocationError /*error*/) {}
inline virtual void onEnableCb(LocationError /*error*/) {}
inline virtual void onDisableCb(LocationError /*error*/) {}
inline virtual void onGnssUpdateConfigCb(
size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
inline virtual void onGnssGetConfigCb(
size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
class GnssDeleteAidingDataRequest : public LocationAPIRequest {
public:
GnssDeleteAidingDataRequest(LocationAPIControlClient& API) : mAPI(API) {}
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onGnssDeleteAidingDataCb(error);
}
LocationAPIControlClient& mAPI;
};
class EnableRequest : public LocationAPIRequest {
public:
EnableRequest(LocationAPIControlClient& API) : mAPI(API) {}
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onEnableCb(error);
}
LocationAPIControlClient& mAPI;
};
class DisableRequest : public LocationAPIRequest {
public:
DisableRequest(LocationAPIControlClient& API) : mAPI(API) {}
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onDisableCb(error);
}
LocationAPIControlClient& mAPI;
};
class GnssUpdateConfigRequest : public LocationAPIRequest {
public:
GnssUpdateConfigRequest(LocationAPIControlClient& API) : mAPI(API) {}
inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* ids) {
mAPI.onGnssUpdateConfigCb(count, errors, ids);
}
LocationAPIControlClient& mAPI;
};
class GnssGetConfigRequest : public LocationAPIRequest {
public:
GnssGetConfigRequest(LocationAPIControlClient& API) : mAPI(API) {}
inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* ids) {
mAPI.onGnssGetConfigCb(count, errors, ids);
}
LocationAPIControlClient& mAPI;
};
private:
pthread_mutex_t mMutex;
LocationControlAPI* mLocationControlAPI;
RequestQueue mRequestQueues[CTRL_REQUEST_MAX];
bool mEnabled;
};
class LocationAPIClientBase {
public:
LocationAPIClientBase();
LocationAPIClientBase(const LocationAPIClientBase&) = delete;
LocationAPIClientBase& operator=(const LocationAPIClientBase&) = delete;
void destroy();
void onLocationApiDestroyCompleteCb();
void locAPISetCallbacks(LocationCallbacks& locationCallbacks);
void removeSession(uint32_t session);
LocationAPIRequest* getRequestBySession(uint32_t session);
// LocationAPI
uint32_t locAPIStartTracking(TrackingOptions& trackingOptions);
void locAPIStopTracking();
void locAPIUpdateTrackingOptions(TrackingOptions& trackingOptions);
int32_t locAPIGetBatchSize();
uint32_t locAPIStartSession(
uint32_t id, uint32_t sessionMode, TrackingOptions&& trackingOptions);
uint32_t locAPIStopSession(uint32_t id);
uint32_t locAPIUpdateSessionOptions(
uint32_t id, uint32_t sessionMode, TrackingOptions&& trackingOptions);
uint32_t locAPIGetBatchedLocations(uint32_t id, size_t count);
uint32_t locAPIAddGeofences(size_t count, uint32_t* ids,
GeofenceOption* options, GeofenceInfo* data);
void locAPIRemoveGeofences(size_t count, uint32_t* ids);
void locAPIModifyGeofences(size_t count, uint32_t* ids, GeofenceOption* options);
void locAPIPauseGeofences(size_t count, uint32_t* ids);
void locAPIResumeGeofences(size_t count, uint32_t* ids, GeofenceBreachTypeMask* mask);
void locAPIRemoveAllGeofences();
void locAPIGnssNiResponse(uint32_t id, GnssNiResponse response);
// callbacks
void onResponseCb(LocationError error, uint32_t id);
void onCollectiveResponseCb(size_t count, LocationError* errors, uint32_t* ids);
void beforeGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification);
inline virtual void onCapabilitiesCb(LocationCapabilitiesMask /*capabilitiesMask*/) {}
inline virtual void onGnssNmeaCb(GnssNmeaNotification /*gnssNmeaNotification*/) {}
inline virtual void onGnssDataCb(GnssDataNotification /*gnssDataNotification*/) {}
inline virtual void onGnssMeasurementsCb(
GnssMeasurementsNotification /*gnssMeasurementsNotification*/) {}
inline virtual void onGnssNHzMeasurementsCb(
GnssMeasurementsNotification /*gnssMeasurementsNotification*/) {}
inline virtual void onTrackingCb(Location /*location*/) {}
inline virtual void onGnssSvCb(GnssSvNotification /*gnssSvNotification*/) {}
inline virtual void onStartTrackingCb(LocationError /*error*/) {}
inline virtual void onStopTrackingCb(LocationError /*error*/) {}
inline virtual void onUpdateTrackingOptionsCb(LocationError /*error*/) {}
inline virtual void onGnssLocationInfoCb(
GnssLocationInfoNotification /*gnssLocationInfoNotification*/) {}
inline virtual void onBatchingCb(size_t /*count*/, Location* /*location*/,
BatchingOptions /*batchingOptions*/) {}
inline virtual void onBatchingStatusCb(BatchingStatusInfo /*batchingStatus*/,
std::list<uint32_t> &/*listOfCompletedTrips*/) {}
void beforeBatchingStatusCb(BatchingStatusInfo batchStatus,
std::list<uint32_t> & tripCompletedList);
inline virtual void onStartBatchingCb(LocationError /*error*/) {}
inline virtual void onStopBatchingCb(LocationError /*error*/) {}
inline virtual void onUpdateBatchingOptionsCb(LocationError /*error*/) {}
inline virtual void onGetBatchedLocationsCb(LocationError /*error*/) {}
inline virtual void onGeofenceBreachCb(
GeofenceBreachNotification /*geofenceBreachNotification*/) {}
inline virtual void onGeofenceStatusCb(
GeofenceStatusNotification /*geofenceStatusNotification*/) {}
inline virtual void onAddGeofencesCb(
size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
inline virtual void onRemoveGeofencesCb(
size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
inline virtual void onModifyGeofencesCb(
size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
inline virtual void onPauseGeofencesCb(
size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
inline virtual void onResumeGeofencesCb(
size_t /*count*/, LocationError* /*errors*/, uint32_t* /*ids*/) {}
inline virtual void onGnssNiCb(uint32_t /*id*/, GnssNiNotification /*gnssNiNotification*/) {}
inline virtual void onGnssNiResponseCb(LocationError /*error*/) {}
inline virtual void onLocationSystemInfoCb(LocationSystemInfo /*locationSystemInfo*/) {}
protected:
virtual ~LocationAPIClientBase();
private:
// private inner classes
typedef struct {
uint32_t id;
uint32_t trackingSession;
uint32_t batchingSession;
uint32_t sessionMode;
} SessionEntity;
template<typename T>
class BiDict {
public:
BiDict() {
pthread_mutex_init(&mBiDictMutex, nullptr);
}
virtual ~BiDict() {
pthread_mutex_destroy(&mBiDictMutex);
}
bool hasId(uint32_t id) {
pthread_mutex_lock(&mBiDictMutex);
bool ret = (mForwardMap.find(id) != mForwardMap.end());
pthread_mutex_unlock(&mBiDictMutex);
return ret;
}
bool hasSession(uint32_t session) {
pthread_mutex_lock(&mBiDictMutex);
bool ret = (mBackwardMap.find(session) != mBackwardMap.end());
pthread_mutex_unlock(&mBiDictMutex);
return ret;
}
void set(uint32_t id, uint32_t session, T& ext) {
pthread_mutex_lock(&mBiDictMutex);
mForwardMap[id] = session;
mBackwardMap[session] = id;
mExtMap[session] = ext;
pthread_mutex_unlock(&mBiDictMutex);
}
void clear() {
pthread_mutex_lock(&mBiDictMutex);
mForwardMap.clear();
mBackwardMap.clear();
mExtMap.clear();
pthread_mutex_unlock(&mBiDictMutex);
}
void rmById(uint32_t id) {
pthread_mutex_lock(&mBiDictMutex);
mBackwardMap.erase(mForwardMap[id]);
mExtMap.erase(mForwardMap[id]);
mForwardMap.erase(id);
pthread_mutex_unlock(&mBiDictMutex);
}
void rmBySession(uint32_t session) {
pthread_mutex_lock(&mBiDictMutex);
mForwardMap.erase(mBackwardMap[session]);
mBackwardMap.erase(session);
mExtMap.erase(session);
pthread_mutex_unlock(&mBiDictMutex);
}
uint32_t getId(uint32_t session) {
pthread_mutex_lock(&mBiDictMutex);
uint32_t ret = 0;
auto it = mBackwardMap.find(session);
if (it != mBackwardMap.end()) {
ret = it->second;
}
pthread_mutex_unlock(&mBiDictMutex);
return ret;
}
uint32_t getSession(uint32_t id) {
pthread_mutex_lock(&mBiDictMutex);
uint32_t ret = 0;
auto it = mForwardMap.find(id);
if (it != mForwardMap.end()) {
ret = it->second;
}
pthread_mutex_unlock(&mBiDictMutex);
return ret;
}
T getExtById(uint32_t id) {
pthread_mutex_lock(&mBiDictMutex);
T ret;
memset(&ret, 0, sizeof(T));
uint32_t session = mForwardMap[id];
if (session > 0) {
auto it = mExtMap.find(session);
if (it != mExtMap.end()) {
ret = it->second;
}
}
pthread_mutex_unlock(&mBiDictMutex);
return ret;
}
T getExtBySession(uint32_t session) {
pthread_mutex_lock(&mBiDictMutex);
T ret;
memset(&ret, 0, sizeof(T));
auto it = mExtMap.find(session);
if (it != mExtMap.end()) {
ret = it->second;
}
pthread_mutex_unlock(&mBiDictMutex);
return ret;
}
std::vector<uint32_t> getAllIds() {
std::vector<uint32_t> ret;
pthread_mutex_lock(&mBiDictMutex);
for (auto idToSessionPair : mForwardMap) {
ret.push_back(idToSessionPair.first);
}
pthread_mutex_unlock(&mBiDictMutex);
return ret;
}
private:
pthread_mutex_t mBiDictMutex;
// mForwarMap mapping id->session
std::map<uint32_t, uint32_t> mForwardMap;
// mBackwardMap mapping session->id
std::map<uint32_t, uint32_t> mBackwardMap;
// mExtMap mapping session->ext
std::map<uint32_t, T> mExtMap;
};
class StartTrackingRequest : public LocationAPIRequest {
public:
StartTrackingRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error, uint32_t id) {
if (error != LOCATION_ERROR_SUCCESS) {
mAPI.removeSession(id);
}
mAPI.onStartTrackingCb(error);
}
LocationAPIClientBase& mAPI;
};
class StopTrackingRequest : public LocationAPIRequest {
public:
StopTrackingRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error, uint32_t id) {
mAPI.onStopTrackingCb(error);
if (error == LOCATION_ERROR_SUCCESS) {
mAPI.removeSession(id);
}
}
LocationAPIClientBase& mAPI;
};
class UpdateTrackingOptionsRequest : public LocationAPIRequest {
public:
UpdateTrackingOptionsRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onUpdateTrackingOptionsCb(error);
}
LocationAPIClientBase& mAPI;
};
class StartBatchingRequest : public LocationAPIRequest {
public:
StartBatchingRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error, uint32_t id) {
if (error != LOCATION_ERROR_SUCCESS) {
mAPI.removeSession(id);
}
mAPI.onStartBatchingCb(error);
}
LocationAPIClientBase& mAPI;
};
class StopBatchingRequest : public LocationAPIRequest {
public:
StopBatchingRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error, uint32_t id) {
mAPI.onStopBatchingCb(error);
if (error == LOCATION_ERROR_SUCCESS) {
mAPI.removeSession(id);
}
}
LocationAPIClientBase& mAPI;
};
class UpdateBatchingOptionsRequest : public LocationAPIRequest {
public:
UpdateBatchingOptionsRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onUpdateBatchingOptionsCb(error);
}
LocationAPIClientBase& mAPI;
};
class GetBatchedLocationsRequest : public LocationAPIRequest {
public:
GetBatchedLocationsRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onGetBatchedLocationsCb(error);
}
LocationAPIClientBase& mAPI;
};
class AddGeofencesRequest : public LocationAPIRequest {
public:
AddGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
for (size_t i = 0; i < count; i++) {
ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
}
LOC_LOGD("%s:]Returned geofence-id: %d in add geofence", __FUNCTION__, *ids);
mAPI.onAddGeofencesCb(count, errors, ids);
free(ids);
}
LocationAPIClientBase& mAPI;
};
class RemoveGeofencesRequest : public LocationAPIRequest {
public:
RemoveGeofencesRequest(LocationAPIClientBase& API,
BiDict<GeofenceBreachTypeMask>* removedGeofenceBiDict) :
mAPI(API), mRemovedGeofenceBiDict(removedGeofenceBiDict) {}
inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
if (nullptr != mRemovedGeofenceBiDict) {
uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
for (size_t i = 0; i < count; i++) {
ids[i] = mRemovedGeofenceBiDict->getId(sessions[i]);
}
LOC_LOGD("%s:]Returned geofence-id: %d in remove geofence", __FUNCTION__, *ids);
mAPI.onRemoveGeofencesCb(count, errors, ids);
free(ids);
delete(mRemovedGeofenceBiDict);
} else {
LOC_LOGE("%s:%d] Unable to access removed geofences data.", __FUNCTION__, __LINE__);
}
}
LocationAPIClientBase& mAPI;
BiDict<GeofenceBreachTypeMask>* mRemovedGeofenceBiDict;
};
class ModifyGeofencesRequest : public LocationAPIRequest {
public:
ModifyGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
for (size_t i = 0; i < count; i++) {
ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
}
mAPI.onModifyGeofencesCb(count, errors, ids);
free(ids);
}
LocationAPIClientBase& mAPI;
};
class PauseGeofencesRequest : public LocationAPIRequest {
public:
PauseGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
for (size_t i = 0; i < count; i++) {
ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
}
mAPI.onPauseGeofencesCb(count, errors, ids);
free(ids);
}
LocationAPIClientBase& mAPI;
};
class ResumeGeofencesRequest : public LocationAPIRequest {
public:
ResumeGeofencesRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onCollectiveResponse(size_t count, LocationError* errors, uint32_t* sessions) {
uint32_t *ids = (uint32_t*)malloc(sizeof(uint32_t) * count);
for (size_t i = 0; i < count; i++) {
ids[i] = mAPI.mGeofenceBiDict.getId(sessions[i]);
}
mAPI.onResumeGeofencesCb(count, errors, ids);
free(ids);
}
LocationAPIClientBase& mAPI;
};
class GnssNiResponseRequest : public LocationAPIRequest {
public:
GnssNiResponseRequest(LocationAPIClientBase& API) : mAPI(API) {}
inline void onResponse(LocationError error, uint32_t /*id*/) {
mAPI.onGnssNiResponseCb(error);
}
LocationAPIClientBase& mAPI;
};
private:
pthread_mutex_t mMutex;
geofenceBreachCallback mGeofenceBreachCallback;
batchingStatusCallback mBatchingStatusCallback;
LocationAPI* mLocationAPI;
RequestQueue mRequestQueues[REQUEST_MAX];
BiDict<GeofenceBreachTypeMask> mGeofenceBiDict;
BiDict<SessionEntity> mSessionBiDict;
int32_t mBatchSize;
bool mTracking;
};
#endif /* LOCATION_API_CLINET_BASE_H */

File diff suppressed because it is too large Load Diff

44
gps/location/Makefile.am Normal file
View File

@@ -0,0 +1,44 @@
ACLOCAL_AMFLAGS = -I m4
AM_CFLAGS = \
-I./ \
-I../utils \
$(LOCPLA_CFLAGS) \
$(GPSUTILS_CFLAGS) \
-std=c++11
liblocation_api_la_SOURCES = \
LocationAPI.cpp \
LocationAPIClientBase.cpp
if USE_EXTERNAL_AP
AM_CFLAGS += -DFEATURE_EXTERNAL_AP
endif
if USE_GLIB
liblocation_api_la_CFLAGS = -DUSE_GLIB $(AM_CFLAGS) @GLIB_CFLAGS@
liblocation_api_la_LDFLAGS = -lstdc++ -Wl,-z,defs -lpthread @GLIB_LIBS@ -shared -version-info 1:0:0
liblocation_api_la_CPPFLAGS = -DUSE_GLIB $(AM_CFLAGS) $(AM_CPPFLAGS) @GLIB_CFLAGS@
else
liblocation_api_la_CFLAGS = $(AM_CFLAGS)
liblocation_api_la_LDFLAGS = -Wl,-z,defs -lpthread -shared -version-info 1:0:0
liblocation_api_la_CPPFLAGS = $(AM_CFLAGS) $(AM_CPPFLAGS)
endif
liblocation_api_la_LIBADD = -lstdc++ -ldl $(GPSUTILS_LIBS)
library_include_HEADERS = \
LocationAPI.h \
LocationAPIClientBase.h \
location_interface.h \
LocationDataTypes.h \
ILocationAPI.h
#Create and Install libraries
lib_LTLIBRARIES = liblocation_api.la
library_includedir = $(pkgincludedir)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = location-api.pc
EXTRA_DIST = $(pkgconfig_DATA)

95
gps/location/configure.ac Normal file
View File

@@ -0,0 +1,95 @@
# configure.ac -- Autoconf script for gps location-api-iface
#
# Process this file with autoconf to produce a configure script
# Requires autoconf tool later than 2.61
AC_PREREQ(2.61)
# Initialize the gps location-api-iface package version 1.0.0
AC_INIT([location-api-iface],1.0.0)
# Does not strictly follow GNU Coding standards
AM_INIT_AUTOMAKE([foreign subdir-objects])
# Disables auto rebuilding of configure, Makefile.ins
AM_MAINTAINER_MODE
# Verifies the --srcdir is correct by checking for the path
AC_CONFIG_SRCDIR([location-api.pc.in])
# defines some macros variable to be included by source
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
# Checks for programs.
AC_PROG_LIBTOOL
AC_PROG_CXX
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_AWK
AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
PKG_PROG_PKG_CONFIG
# Checks for libraries.
PKG_CHECK_MODULES([GPSUTILS], [gps-utils])
AC_SUBST([GPSUTILS_CFLAGS])
AC_SUBST([GPSUTILS_LIBS])
AC_ARG_WITH([core_includes],
AC_HELP_STRING([--with-core-includes=@<:@dir@:>@],
[Specify the location of the core headers]),
[core_incdir=$withval],
with_core_includes=no)
if test "x$with_core_includes" != "xno"; then
CPPFLAGS="${CPPFLAGS} -I${core_incdir}"
fi
AC_ARG_WITH([locpla_includes],
AC_HELP_STRING([--with-locpla-includes=@<:@dir@:>@],
[Specify the path to locpla-includes in loc-pla_git.bb]),
[locpla_incdir=$withval],
with_locpla_includes=no)
if test "x${with_locpla_includes}" != "xno"; then
AC_SUBST(LOCPLA_CFLAGS, "-I${locpla_incdir}")
fi
AC_SUBST([CPPFLAGS])
AC_ARG_WITH([glib],
AC_HELP_STRING([--with-glib],
[enable glib, building HLOS systems which use glib]))
if (test "x${with_glib}" = "xyes"); then
AC_DEFINE(ENABLE_USEGLIB, 1, [Define if HLOS systems uses glib])
PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes,
AC_MSG_ERROR(GThread >= 2.16 is required))
PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, dummy=yes,
AC_MSG_ERROR(GLib >= 2.16 is required))
GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS"
GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS"
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
fi
AM_CONDITIONAL(USE_GLIB, test "x${with_glib}" = "xyes")
# External AP
AC_ARG_WITH([external_ap],
AC_HELP_STRING([--with-external_ap=@<:@dir@:>@],
[Using External Application Processor]),
[],
with_external_ap=no)
if test "x$with_external_ap" != "xno"; then
CPPFLAGS="${CPPFLAGS} -DFEATURE_EXTERNAL_AP"
fi
AM_CONDITIONAL(USE_EXTERNAL_AP, test "x${with_external_ap}" = "xyes")
AC_CONFIG_FILES([ \
Makefile \
location-api.pc \
])
AC_OUTPUT

View File

@@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: location-api
Description: Location API
Version: @VERSION
Libs: -L${libdir} -llocation_api
Cflags: -I${includedir}/location-api

View File

@@ -0,0 +1,152 @@
/* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef LOCATION_INTERFACE_H
#define LOCATION_INTERFACE_H
#include <LocationAPI.h>
#include <gps_extended_c.h>
#include <functional>
/* Used for callback to deliver GNSS energy consumed */
/** @fn
@brief Used by query API that retrieves energy consumed by
modem GNSS engine.
@param gnssEnergyConsumedFromFirstBoot:
Energy consumed by the GNSS engine since the first bootup
in units of 0.1 milli watt seconds.
A value of 0xffffffffffffffff indicates an invalid reading.
*/
typedef std::function<void(
uint64_t gnssEnergyConsumedFromFirstBoot
)> GnssEnergyConsumedCallback;
typedef void (*removeClientCompleteCallback)(LocationAPI* client);
struct GnssInterface {
size_t size;
void (*initialize)(void);
void (*deinitialize)(void);
void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb);
void (*requestCapabilities)(LocationAPI* client);
uint32_t (*startTracking)(LocationAPI* client, TrackingOptions&);
void (*updateTrackingOptions)(LocationAPI* client, uint32_t id, TrackingOptions&);
void (*stopTracking)(LocationAPI* client, uint32_t id);
void (*gnssNiResponse)(LocationAPI* client, uint32_t id, GnssNiResponse response);
void (*setControlCallbacks)(LocationControlCallbacks& controlCallbacks);
uint32_t (*enable)(LocationTechnologyType techType);
void (*disable)(uint32_t id);
uint32_t* (*gnssUpdateConfig)(const GnssConfig& config);
uint32_t* (*gnssGetConfig)(GnssConfigFlagsMask config);
void (*gnssUpdateSvTypeConfig)(GnssSvTypeConfig& config);
void (*gnssGetSvTypeConfig)(GnssSvTypeConfigCallback& callback);
void (*gnssResetSvTypeConfig)();
uint32_t (*gnssDeleteAidingData)(GnssAidingData& data);
void (*gnssUpdateXtraThrottle)(const bool enabled);
void (*injectLocation)(double latitude, double longitude, float accuracy);
void (*injectTime)(int64_t time, int64_t timeReference, int32_t uncertainty);
void (*agpsInit)(const AgpsCbInfo& cbInfo);
void (*agpsDataConnOpen)(AGpsExtType agpsType, const char* apnName, int apnLen, int ipType);
void (*agpsDataConnClosed)(AGpsExtType agpsType);
void (*agpsDataConnFailed)(AGpsExtType agpsType);
void (*getDebugReport)(GnssDebugReport& report);
void (*updateConnectionStatus)(bool connected, int8_t type, bool roaming,
NetworkHandle networkHandle, std::string& apn);
void (*odcpiInit)(const OdcpiRequestCallback& callback, OdcpiPrioritytype priority);
void (*odcpiInject)(const Location& location);
void (*blockCPI)(double latitude, double longitude, float accuracy,
int blockDurationMsec, double latLonDiffThreshold);
void (*getGnssEnergyConsumed)(GnssEnergyConsumedCallback energyConsumedCb);
void (*enableNfwLocationAccess)(std::vector<std::string>& enabledNfws);
void (*nfwInit)(const NfwCbInfo& cbInfo);
void (*getPowerStateChanges)(std::function<void(bool)> powerStateCb);
void (*injectLocationExt)(const GnssLocationInfoNotification &locationInfo);
void (*updateBatteryStatus)(bool charging);
void (*updateSystemPowerState)(PowerStateType systemPowerState);
uint32_t (*setConstrainedTunc) (bool enable, float tuncConstraint, uint32_t energyBudget);
uint32_t (*setPositionAssistedClockEstimator) (bool enable);
uint32_t (*gnssUpdateSvConfig)(const GnssSvTypeConfig& constellationEnablementConfig,
const GnssSvIdConfig& blacklistSvConfig);
uint32_t (*configLeverArm)(const LeverArmConfigInfo& configInfo);
bool (*measCorrInit)(const measCorrSetCapabilitiesCb setCapabilitiesCb);
bool (*measCorrSetCorrections)(const GnssMeasurementCorrections gnssMeasCorr);
void (*measCorrClose)();
uint32_t (*antennaInfoInit)(const antennaInfoCb antennaInfoCallback);
void (*antennaInfoClose) ();
uint32_t (*configRobustLocation)(bool enable, bool enableForE911);
uint32_t (*configMinGpsWeek)(uint16_t minGpsWeek);
uint32_t (*configDeadReckoningEngineParams)(const DeadReckoningEngineConfig& dreConfig);
void (*updateNTRIPGGAConsent)(bool consentAccepted);
void (*enablePPENtripStream)(const GnssNtripConnectionParams& params, bool enableRTKEngine);
void (*disablePPENtripStream)();
uint32_t (*gnssUpdateSecondaryBandConfig)(const GnssSvTypeConfig& secondaryBandConfig);
uint32_t (*gnssGetSecondaryBandConfig)();
void (*resetNetworkInfo)();
uint32_t (*configEngineRunState)(PositioningEngineMask engType,
LocEngineRunState engState);
uint32_t (*configOutputNmeaTypes)(GnssNmeaTypesMask enabledNmeaTypes);
void (*powerIndicationInit)(const powerIndicationCb powerIndicationCallback);
void (*powerIndicationRequest)();
void (*setAddressRequestCb)(std::function<void(const Location&)> addressRequestCb);
void (*injectLocationAndAddr)(const Location& location, const GnssCivicAddress& addr);
uint32_t (*setOptInStatus)(bool userConsent);
};
struct BatchingInterface {
size_t size;
void (*initialize)(void);
void (*deinitialize)(void);
void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb);
void (*requestCapabilities)(LocationAPI* client);
uint32_t (*startBatching)(LocationAPI* client, BatchingOptions&);
void (*stopBatching)(LocationAPI* client, uint32_t id);
void (*updateBatchingOptions)(LocationAPI* client, uint32_t id, BatchingOptions&);
void (*getBatchedLocations)(LocationAPI* client, uint32_t id, size_t count);
void (*updateSystemPowerState)(PowerStateType systemPowerState);
};
struct GeofenceInterface {
size_t size;
void (*initialize)(void);
void (*deinitialize)(void);
void (*addClient)(LocationAPI* client, const LocationCallbacks& callbacks);
void (*removeClient)(LocationAPI* client, removeClientCompleteCallback rmClientCb);
void (*requestCapabilities)(LocationAPI* client);
uint32_t* (*addGeofences)(LocationAPI* client, size_t count, GeofenceOption*, GeofenceInfo*);
void (*removeGeofences)(LocationAPI* client, size_t count, uint32_t* ids);
void (*modifyGeofences)(LocationAPI* client, size_t count, uint32_t* ids,
GeofenceOption* options);
void (*pauseGeofences)(LocationAPI* client, size_t count, uint32_t* ids);
void (*resumeGeofences)(LocationAPI* client, size_t count, uint32_t* ids);
void (*updateSystemPowerState)(PowerStateType systemPowerState);
};
#endif /* LOCATION_INTERFACE_H */