SGCMarkus 64ab05b033 sm8250-common: import location from LA.UM.9.12.r1-13500.01-SMxx50.QSSI12.0
Change-Id: If93ba9b50dc3bb07a4ba81694187e99f58dd172c
2022-03-23 22:23:56 +01:00

1611 lines
63 KiB
C++

/* Copyright (c) 2018-2020 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.
*/
#include <stdint.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include <memory>
#include <SystemStatus.h>
#include <LocationApiMsg.h>
#include <gps_extended_c.h>
#ifdef POWERMANAGER_ENABLED
#include <PowerEvtHandler.h>
#endif
#include <LocHalDaemonClientHandler.h>
#include <LocationApiService.h>
#include <location_interface.h>
#include <loc_misc_utils.h>
using namespace std;
#define MAX_GEOFENCE_COUNT (20)
#define MAINT_TIMER_INTERVAL_MSEC (60000)
#define AUTO_START_CLIENT_NAME "default"
typedef void* (getLocationInterface)();
/******************************************************************************
LocationApiService - static members
******************************************************************************/
LocationApiService* LocationApiService::mInstance = nullptr;
std::mutex LocationApiService::mMutex;
/******************************************************************************
LocHaldIpcListener
******************************************************************************/
class LocHaldIpcListener : public ILocIpcListener {
protected:
LocationApiService& mService;
public:
inline LocHaldIpcListener(LocationApiService& service) : mService(service) {}
// override from LocIpc
inline void onReceive(const char* data, uint32_t length,
const LocIpcRecver* recver) override {
mService.processClientMsg(data, length);
}
};
class LocHaldLocalIpcListener : public LocHaldIpcListener {
const string mClientSockPath = SOCKET_LOC_CLIENT_DIR;
const string mClientSockPathnamePrefix = SOCKET_LOC_CLIENT_DIR LOC_CLIENT_NAME_PREFIX;
public:
inline LocHaldLocalIpcListener(LocationApiService& service) : LocHaldIpcListener(service) {}
inline void onListenerReady() override {
if (0 != chown(SOCKET_TO_LOCATION_HAL_DAEMON, UID_GPS, GID_LOCCLIENT)) {
LOC_LOGe("chown to group locclient failed %s", strerror(errno));
}
// traverse client sockets directory - then broadcast READY message
LOC_LOGd(">-- onListenerReady Finding client sockets...");
DIR *dirp = opendir(mClientSockPath.c_str());
if (!dirp) {
LOC_LOGw("%s not created", mClientSockPath.c_str());
return;
}
struct dirent *dp = nullptr;
struct stat sbuf = {0};
while (nullptr != (dp = readdir(dirp))) {
std::string fname = mClientSockPath;
fname += dp->d_name;
if (-1 == lstat(fname.c_str(), &sbuf)) {
continue;
}
if ('.' == (dp->d_name[0])) {
continue;
}
if (0 == fname.compare(0, mClientSockPathnamePrefix.size(),
mClientSockPathnamePrefix)) {
shared_ptr<LocIpcSender> sender = LocHalDaemonClientHandler::createSender(fname);
LocAPIHalReadyIndMsg msg(SERVICE_NAME, &mService.mPbufMsgConv);
string pbStr;
if (msg.serializeToProtobuf(pbStr)) {
LOC_LOGd("<-- Sending ready to socket: %s, msg size %d",
fname.c_str(), pbStr.size());
LocIpc::send(*sender, reinterpret_cast<const uint8_t*>(pbStr.c_str()),
pbStr.size());
} else {
LOC_LOGe("LocAPIHalReadyIndMsg serializeToProtobuf failed");
}
}
}
closedir(dirp);
}
};
/******************************************************************************
LocationApiService - constructors
******************************************************************************/
LocationApiService::LocationApiService(const configParamToRead & configParamRead) :
mLocationControlId(0),
mAutoStartGnss(configParamRead.autoStartGnss),
mPowerState(POWER_STATE_UNKNOWN),
mPositionMode((GnssSuplMode)configParamRead.positionMode),
mMsgTask("LocHalDaemonMaintenanceMsgTask"),
mMaintTimer(this),
mGtpWwanSsLocationApi(nullptr),
mOptInTerrestrialService(-1)
#ifdef POWERMANAGER_ENABLED
,mPowerEventObserver(nullptr)
#endif
{
LOC_LOGd("AutoStartGnss=%u", mAutoStartGnss);
LOC_LOGd("GnssSessionTbfMs=%u", configParamRead.gnssSessionTbfMs);
LOC_LOGd("DeleteAllBeforeAutoStart=%u", configParamRead.deleteAllBeforeAutoStart);
LOC_LOGd("DeleteAllOnEnginesMask=%u", configParamRead.posEngineMask);
LOC_LOGd("PositionMode=%u", configParamRead.positionMode);
// create Location control API
mControlCallabcks.size = sizeof(mControlCallabcks);
mControlCallabcks.responseCb = [this](LocationError err, uint32_t id) {
onControlResponseCallback(err, id);
};
mControlCallabcks.collectiveResponseCb =
[this](size_t count, LocationError *errs, uint32_t *ids) {
onControlCollectiveResponseCallback(count, errs, ids);
};
mControlCallabcks.gnssConfigCb =
[this](uint32_t sessionId, const GnssConfig& config) {
onGnssConfigCallback(sessionId, config);
};
mLocationControlApi = LocationControlAPI::createInstance(mControlCallabcks);
if (nullptr == mLocationControlApi) {
LOC_LOGd("Failed to create LocationControlAPI");
return;
}
// enable
mLocationControlId = mLocationControlApi->enable(LOCATION_TECHNOLOGY_TYPE_GNSS);
LOC_LOGd("-->enable=%u", mLocationControlId);
// this is a unique id assigned to this daemon - will be used when disable
#ifdef POWERMANAGER_ENABLED
// register power event handler
mPowerEventObserver = PowerEvtHandler::getPwrEvtHandler(this);
if (nullptr == mPowerEventObserver) {
LOC_LOGe("Failed to regiseter Powerevent handler");
return;
}
#endif
mMaintTimer.start(MAINT_TIMER_INTERVAL_MSEC, false);
// create a default client if enabled by config
if (mAutoStartGnss) {
if ((configParamRead.deleteAllBeforeAutoStart) &&
(configParamRead.posEngineMask != 0)) {
GnssAidingData aidingData = {};
aidingData.deleteAll = true;
aidingData.posEngineMask = configParamRead.posEngineMask;
mLocationControlApi->gnssDeleteAidingData(aidingData);
}
LOC_LOGd("--> Starting a default client...");
LocHalDaemonClientHandler* pClient =
new LocHalDaemonClientHandler(this, AUTO_START_CLIENT_NAME, LOCATION_CLIENT_API);
mClients.emplace(AUTO_START_CLIENT_NAME, pClient);
pClient->updateSubscription(
E_LOC_CB_GNSS_LOCATION_INFO_BIT | E_LOC_CB_GNSS_SV_BIT);
LocationOptions locationOption = {};
locationOption.size = sizeof(locationOption);
locationOption.minInterval = configParamRead.gnssSessionTbfMs;
locationOption.minDistance = 0;
locationOption.mode = mPositionMode;
pClient->startTracking(locationOption);
pClient->mTracking = true;
loc_boot_kpi_marker("L - Auto Session Start");
pClient->mPendingMessages.push(E_LOCAPI_START_TRACKING_MSG_ID);
}
// start receiver - never return
LOC_LOGd("Ready, start Ipc Receivers");
auto recver = LocIpc::getLocIpcLocalRecver(make_shared<LocHaldLocalIpcListener>(*this),
SOCKET_TO_LOCATION_HAL_DAEMON);
// blocking: set to false
mIpc.startNonBlockingListening(recver);
mBlockingRecver = LocIpc::getLocIpcQrtrRecver(make_shared<LocHaldIpcListener>(*this),
LOCATION_CLIENT_API_QSOCKET_HALDAEMON_SERVICE_ID,
LOCATION_CLIENT_API_QSOCKET_HALDAEMON_INSTANCE_ID);
mIpc.startBlockingListening(*mBlockingRecver);
}
LocationApiService::~LocationApiService() {
mIpc.stopNonBlockingListening();
mIpc.stopBlockingListening(*mBlockingRecver);
// free resource associated with the client
for (auto each : mClients) {
LOC_LOGd(">-- deleted client [%s]", each.first.c_str());
each.second->cleanup();
}
// delete location contorol API handle
mLocationControlApi->disable(mLocationControlId);
mLocationControlApi->destroy();
}
/******************************************************************************
LocationApiService - implementation - registration
******************************************************************************/
void LocationApiService::processClientMsg(const char* data, uint32_t length) {
string mMsgData(data, length);
// parse received message
// Protobuff Encoding enabled, so we need to convert the message from proto
// encoded format to local structure
PBLocAPIMsgHeader pbLocApiMsg;
if (0 == pbLocApiMsg.ParseFromString(mMsgData)) {
LOC_LOGe("Failed to parse pbLocApiMsg from input stream!! length: %u",
mMsgData.length());
return;
}
ELocMsgID eLocMsgid = mPbufMsgConv.getEnumForPBELocMsgID(pbLocApiMsg.msgid());
string sockName = pbLocApiMsg.msocketname();
uint32_t msgVer = pbLocApiMsg.msgversion();
uint32_t payloadSize = pbLocApiMsg.payloadsize();
// pbLocApiMsg.payload() contains the payload data.
LOC_LOGi(">-- onReceive Rcvd msg id: %d, remote client: %s, payload size: %d", eLocMsgid,
sockName.c_str(), payloadSize);
LocAPIMsgHeader locApiMsg(sockName.c_str(), eLocMsgid);
// throw away msg that does not come from location hal daemon client, e.g. LCA/LIA
if (false == locApiMsg.isValidClientMsg(payloadSize)) {
return;
}
switch (eLocMsgid) {
case E_LOCAPI_CLIENT_REGISTER_MSG_ID: {
// new client
PBLocAPIClientRegisterReqMsg pbLocApiClientRegReqMsg;
if (0 == pbLocApiClientRegReqMsg.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiClientRegReqMsg from payload!!");
return;
}
LocAPIClientRegisterReqMsg msg(pbLocApiMsg.msocketname().c_str(),
pbLocApiClientRegReqMsg, &mPbufMsgConv);
newClient(reinterpret_cast<LocAPIClientRegisterReqMsg*>(&msg));
break;
}
case E_LOCAPI_CLIENT_DEREGISTER_MSG_ID: {
// delete client
LocAPIClientDeregisterReqMsg msg(sockName.c_str(), &mPbufMsgConv);
deleteClient(reinterpret_cast<LocAPIClientDeregisterReqMsg*>(&msg));
break;
}
case E_LOCAPI_START_TRACKING_MSG_ID: {
// start
PBLocAPIStartTrackingReqMsg pbLocApiStartTrackMsg;
if (0 == pbLocApiStartTrackMsg.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiStartTrackMsg from payload!!");
return;
}
LocAPIStartTrackingReqMsg msg(sockName.c_str(), pbLocApiStartTrackMsg, &mPbufMsgConv);
startTracking(reinterpret_cast<LocAPIStartTrackingReqMsg*>(&msg));
break;
}
case E_LOCAPI_STOP_TRACKING_MSG_ID: {
// stop
LocAPIStopTrackingReqMsg msg(sockName.c_str(), &mPbufMsgConv);
stopTracking(reinterpret_cast<LocAPIStopTrackingReqMsg*>(&msg));
break;
}
case E_LOCAPI_UPDATE_CALLBACKS_MSG_ID: {
// update subscription
PBLocAPIUpdateCallbacksReqMsg pbLocApiUpdateCbsReqMsg;
if (0 == pbLocApiUpdateCbsReqMsg.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiUpdateCbsReqMsg from payload!!");
return;
}
LocAPIUpdateCallbacksReqMsg msg(sockName.c_str(), pbLocApiUpdateCbsReqMsg,
&mPbufMsgConv);
updateSubscription(reinterpret_cast<LocAPIUpdateCallbacksReqMsg*>(&msg));
break;
}
case E_LOCAPI_UPDATE_TRACKING_OPTIONS_MSG_ID: {
PBLocAPIUpdateTrackingOptionsReqMsg pbLocApiUpdateTrackOptMsg;
if (0 == pbLocApiUpdateTrackOptMsg.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiUpdateTrackOptMsg from payload!!");
return;
}
LocAPIUpdateTrackingOptionsReqMsg msg(sockName.c_str(), pbLocApiUpdateTrackOptMsg,
&mPbufMsgConv);
updateTrackingOptions(reinterpret_cast <LocAPIUpdateTrackingOptionsReqMsg*>(&msg));
break;
}
case E_LOCAPI_START_BATCHING_MSG_ID: {
// start
PBLocAPIStartBatchingReqMsg pbLocApiStartBatchReq;
if (0 == pbLocApiStartBatchReq.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiStartBatchReq from payload!!");
return;
}
LocAPIStartBatchingReqMsg msg(sockName.c_str(), pbLocApiStartBatchReq, &mPbufMsgConv);
startBatching(reinterpret_cast<LocAPIStartBatchingReqMsg*>(&msg));
break;
}
case E_LOCAPI_STOP_BATCHING_MSG_ID: {
// stop
LocAPIStopBatchingReqMsg msg(sockName.c_str(), &mPbufMsgConv);
stopBatching(reinterpret_cast<LocAPIStopBatchingReqMsg*>(&msg));
break;
}
case E_LOCAPI_UPDATE_BATCHING_OPTIONS_MSG_ID: {
PBLocAPIUpdateBatchingOptionsReqMsg pbLocApiUpdateBatch;
if (0 == pbLocApiUpdateBatch.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiUpdateBatch from payload!!");
return;
}
LocAPIUpdateBatchingOptionsReqMsg msg(sockName.c_str(), pbLocApiUpdateBatch,
&mPbufMsgConv);
updateBatchingOptions(reinterpret_cast <LocAPIUpdateBatchingOptionsReqMsg*>(&msg));
break;
}
case E_LOCAPI_ADD_GEOFENCES_MSG_ID: {
PBLocAPIAddGeofencesReqMsg pbLocApiAddGf;
if (0 == pbLocApiAddGf.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiAddGf from payload!!");
return;
}
LocAPIAddGeofencesReqMsg msg(sockName.c_str(), pbLocApiAddGf, &mPbufMsgConv);
addGeofences(reinterpret_cast<LocAPIAddGeofencesReqMsg*>(&msg));
break;
}
case E_LOCAPI_REMOVE_GEOFENCES_MSG_ID: {
PBLocAPIRemoveGeofencesReqMsg pbLocApiRnGfReq;
if (0 == pbLocApiRnGfReq.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiRnGfReq from payload!!");
return;
}
LocAPIRemoveGeofencesReqMsg msg(sockName.c_str(), pbLocApiRnGfReq, &mPbufMsgConv);
removeGeofences(reinterpret_cast<LocAPIRemoveGeofencesReqMsg*>(&msg));
break;
}
case E_LOCAPI_MODIFY_GEOFENCES_MSG_ID: {
PBLocAPIModifyGeofencesReqMsg pbLocApiModGf;
if (0 == pbLocApiModGf.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiModGf from payload!!");
return;
}
LocAPIModifyGeofencesReqMsg msg(sockName.c_str(), pbLocApiModGf, &mPbufMsgConv);
modifyGeofences(reinterpret_cast<LocAPIModifyGeofencesReqMsg*>(&msg));
break;
}
case E_LOCAPI_PAUSE_GEOFENCES_MSG_ID: {
PBLocAPIPauseGeofencesReqMsg pbLocApiPauseGf;
if (0 == pbLocApiPauseGf.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiPauseGf from payload!!");
return;
}
LocAPIPauseGeofencesReqMsg msg(sockName.c_str(), pbLocApiPauseGf, &mPbufMsgConv);
pauseGeofences(reinterpret_cast<LocAPIPauseGeofencesReqMsg*>(&msg));
break;
}
case E_LOCAPI_RESUME_GEOFENCES_MSG_ID: {
PBLocAPIResumeGeofencesReqMsg pbLocApiResumeGf;
if (0 == pbLocApiResumeGf.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiResumeGf from payload!!");
return;
}
LocAPIResumeGeofencesReqMsg msg(sockName.c_str(), pbLocApiResumeGf, &mPbufMsgConv);
resumeGeofences(reinterpret_cast<LocAPIResumeGeofencesReqMsg*>(&msg));
break;
}
case E_LOCAPI_CONTROL_UPDATE_NETWORK_AVAILABILITY_MSG_ID: {
PBLocAPIUpdateNetworkAvailabilityReqMsg pbLocApiUpdateNetwAvail;
if (0 == pbLocApiUpdateNetwAvail.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiUpdateNetwAvail from payload!!");
return;
}
LocAPIUpdateNetworkAvailabilityReqMsg msg(sockName.c_str(), pbLocApiUpdateNetwAvail,
&mPbufMsgConv);
updateNetworkAvailability(msg.mAvailability);
break;
}
case E_LOCAPI_GET_GNSS_ENGERY_CONSUMED_MSG_ID: {
getGnssEnergyConsumed(sockName.c_str());
break;
}
case E_LOCAPI_GET_SINGLE_TERRESTRIAL_POS_REQ_MSG_ID: {
PBLocAPIGetSingleTerrestrialPosReqMsg pbMsg;
if (0 == pbMsg.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse PBLocAPIGetSingleTerrestrialPosReqMsg from payload!!");
return;
}
LocAPIGetSingleTerrestrialPosReqMsg msg(sockName.c_str(), pbMsg, &mPbufMsgConv);
getSingleTerrestrialPos(&msg);
break;
}
case E_LOCAPI_PINGTEST_MSG_ID: {
PBLocAPIPingTestReqMsg pbLocApiPingTestMsg;
if (0 == pbLocApiPingTestMsg.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiPingTestMsg from payload!!");
return;
}
LocAPIPingTestReqMsg msg(sockName.c_str(), pbLocApiPingTestMsg, &mPbufMsgConv);
pingTest(reinterpret_cast<LocAPIPingTestReqMsg*>(&msg));
break;
}
// location configuration API
case E_INTAPI_CONFIG_CONSTRAINTED_TUNC_MSG_ID: {
PBLocConfigConstrainedTuncReqMsg pbLocApiConfConstrTunc;
if (0 == pbLocApiConfConstrTunc.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiConfConstrTunc from payload!!");
return;
}
LocConfigConstrainedTuncReqMsg msg(sockName.c_str(), pbLocApiConfConstrTunc,
&mPbufMsgConv);
configConstrainedTunc(reinterpret_cast<LocConfigConstrainedTuncReqMsg*>(&msg));
break;
}
case E_INTAPI_CONFIG_POSITION_ASSISTED_CLOCK_ESTIMATOR_MSG_ID: {
PBLocConfigPositionAssistedClockEstimatorReqMsg pbLocApiConfPosAsstdClockEst;
if (0 == pbLocApiConfPosAsstdClockEst.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiConfPosAsstdClockEst from payload!!");
return;
}
LocConfigPositionAssistedClockEstimatorReqMsg msg(sockName.c_str(),
pbLocApiConfPosAsstdClockEst, &mPbufMsgConv);
configPositionAssistedClockEstimator(reinterpret_cast
<LocConfigPositionAssistedClockEstimatorReqMsg*>(&msg));
break;
}
case E_INTAPI_CONFIG_SV_CONSTELLATION_MSG_ID: {
PBLocConfigSvConstellationReqMsg pbLocApiConfSvConstReqMsg;
if (0 == pbLocApiConfSvConstReqMsg.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocApiConfSvConstReqMsg from payload!!");
return;
}
LocConfigSvConstellationReqMsg msg(sockName.c_str(), pbLocApiConfSvConstReqMsg,
&mPbufMsgConv);
configConstellations(reinterpret_cast<LocConfigSvConstellationReqMsg*>(&msg));
break;
}
case E_INTAPI_CONFIG_CONSTELLATION_SECONDARY_BAND_MSG_ID: {
PBLocConfigConstellationSecondaryBandReqMsg pbLocCfgConstlSecBandReqMsg;
if (0 == pbLocCfgConstlSecBandReqMsg.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocCfgConstlSecBandReqMsg from payload!!");
return;
}
LocConfigConstellationSecondaryBandReqMsg msg(sockName.c_str(),
pbLocCfgConstlSecBandReqMsg, &mPbufMsgConv);
configConstellationSecondaryBand(reinterpret_cast
<LocConfigConstellationSecondaryBandReqMsg*>(&msg));
break;
}
case E_INTAPI_CONFIG_AIDING_DATA_DELETION_MSG_ID: {
PBLocConfigAidingDataDeletionReqMsg pbLocConfAidDataDelMsg;
if (0 == pbLocConfAidDataDelMsg.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocConfAidDataDelMsg from payload!!");
return;
}
LocConfigAidingDataDeletionReqMsg msg(sockName.c_str(), pbLocConfAidDataDelMsg,
&mPbufMsgConv);
configAidingDataDeletion(reinterpret_cast<LocConfigAidingDataDeletionReqMsg*>(&msg));
break;
}
case E_INTAPI_CONFIG_LEVER_ARM_MSG_ID: {
PBLocConfigLeverArmReqMsg pbLocConfLeverArmMsg;
if (0 == pbLocConfLeverArmMsg.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocConfLeverArmMsg from payload!!");
return;
}
LocConfigLeverArmReqMsg msg(sockName.c_str(), pbLocConfLeverArmMsg, &mPbufMsgConv);
configLeverArm(reinterpret_cast<LocConfigLeverArmReqMsg*>(&msg));
break;
}
case E_INTAPI_CONFIG_ROBUST_LOCATION_MSG_ID: {
PBLocConfigRobustLocationReqMsg pbLocConfRobustLocMsg;
if (0 == pbLocConfRobustLocMsg.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocConfRobustLocMsg from payload!!");
return;
}
LocConfigRobustLocationReqMsg msg(sockName.c_str(), pbLocConfRobustLocMsg,
&mPbufMsgConv);
configRobustLocation(reinterpret_cast<LocConfigRobustLocationReqMsg*>(&msg));
break;
}
case E_INTAPI_CONFIG_MIN_GPS_WEEK_MSG_ID: {
PBLocConfigMinGpsWeekReqMsg pbLocConfMinGpsWeek;
if (0 == pbLocConfMinGpsWeek.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocConfMinGpsWeek from payload!!");
return;
}
LocConfigMinGpsWeekReqMsg msg(sockName.c_str(), pbLocConfMinGpsWeek, &mPbufMsgConv);
configMinGpsWeek(reinterpret_cast<LocConfigMinGpsWeekReqMsg*>(&msg));
break;
}
case E_INTAPI_CONFIG_DEAD_RECKONING_ENGINE_MSG_ID: {
PBLocConfigDrEngineParamsReqMsg pbLocCfgDrEngParamReq;
if (0 == pbLocCfgDrEngParamReq.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocCfgDrEngParamReq from payload!!");
return;
}
LocConfigDrEngineParamsReqMsg msg(sockName.c_str(), pbLocCfgDrEngParamReq,
&mPbufMsgConv);
configDeadReckoningEngineParams(
reinterpret_cast<LocConfigDrEngineParamsReqMsg*>(&msg));
break;
}
case E_INTAPI_CONFIG_MIN_SV_ELEVATION_MSG_ID: {
PBLocConfigMinSvElevationReqMsg pbLocConfMinSvElev;
if (0 == pbLocConfMinSvElev.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocConfMinSvElev from payload!!");
return;
}
LocConfigMinSvElevationReqMsg msg(sockName.c_str(), pbLocConfMinSvElev, &mPbufMsgConv);
configMinSvElevation(reinterpret_cast<LocConfigMinSvElevationReqMsg*>(&msg));
break;
}
case E_INTAPI_CONFIG_ENGINE_RUN_STATE_MSG_ID: {
PBLocConfigEngineRunStateReqMsg pbLocConfEngineRunState;
if (0 == pbLocConfEngineRunState.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse pbLocConfEngineRunState from payload!!");
return;
}
LocConfigEngineRunStateReqMsg msg(sockName.c_str(),
pbLocConfEngineRunState,
&mPbufMsgConv);
configEngineRunState(reinterpret_cast<LocConfigEngineRunStateReqMsg*>(&msg));
break;
}
case E_INTAPI_CONFIG_USER_CONSENT_TERRESTRIAL_POSITIONING_MSG_ID: {
PBLocConfigUserConsentTerrestrialPositioningReqMsg pbMsg;
if (0 == pbMsg.ParseFromString(pbLocApiMsg.payload())) {
LOC_LOGe("Failed to parse PBLocConfigUserConsentTerrestrialPositioningReqMsg!!");
return;
}
LocConfigUserConsentTerrestrialPositioningReqMsg msg(
sockName.c_str(), pbMsg, &mPbufMsgConv);
configUserConsentTerrestrialPositioning(reinterpret_cast
<LocConfigUserConsentTerrestrialPositioningReqMsg*>(&msg));
break;
}
case E_INTAPI_GET_ROBUST_LOCATION_CONFIG_REQ_MSG_ID: {
getGnssConfig(&locApiMsg, GNSS_CONFIG_FLAGS_ROBUST_LOCATION_BIT);
break;
}
case E_INTAPI_GET_MIN_GPS_WEEK_REQ_MSG_ID: {
getGnssConfig(&locApiMsg, GNSS_CONFIG_FLAGS_MIN_GPS_WEEK_BIT);
break;
}
case E_INTAPI_GET_MIN_SV_ELEVATION_REQ_MSG_ID: {
getGnssConfig(&locApiMsg, GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT);
break;
}
case E_INTAPI_GET_CONSTELLATION_SECONDARY_BAND_CONFIG_REQ_MSG_ID: {
getConstellationSecondaryBandConfig(
(const LocConfigGetConstellationSecondaryBandConfigReqMsg*) &locApiMsg);
break;
}
default: {
LOC_LOGe("Unknown message with id: %d ", eLocMsgid);
break;
}
}
}
/******************************************************************************
LocationApiService - implementation - registration
******************************************************************************/
void LocationApiService::newClient(LocAPIClientRegisterReqMsg *pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
std::string clientname(pMsg->mSocketName);
// if this name is already used return error
if (mClients.find(clientname) != mClients.end()) {
LOC_LOGe("invalid client=%s already existing", clientname.c_str());
return;
}
// store it in client property database
LocHalDaemonClientHandler *pClient =
new LocHalDaemonClientHandler(this, clientname, pMsg->mClientType);
if (!pClient) {
LOC_LOGe("failed to register client=%s", clientname.c_str());
return;
}
mClients.emplace(clientname, pClient);
LOC_LOGi(">-- registered new client=%s", clientname.c_str());
}
void LocationApiService::deleteClient(LocAPIClientDeregisterReqMsg *pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
std::string clientname(pMsg->mSocketName);
deleteClientbyName(clientname);
}
void LocationApiService::deleteClientbyName(const std::string clientname) {
LOC_LOGi(">-- deleteClient client=%s", clientname.c_str());
// delete this client from property db
LocHalDaemonClientHandler* pClient = getClient(clientname);
if (!pClient) {
LOC_LOGe(">-- deleteClient invlalid client=%s", clientname.c_str());
return;
}
mClients.erase(clientname);
mTerrestrialFixReqs.erase(clientname);
pClient->cleanup();
}
/******************************************************************************
LocationApiService - implementation - tracking
******************************************************************************/
void LocationApiService::startTracking(LocAPIStartTrackingReqMsg *pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (!pClient) {
LOC_LOGe(">-- start invlalid client=%s", pMsg->mSocketName);
return;
}
LocationOptions locationOption = pMsg->locOptions;
// set the mode according to the master position mode
locationOption.mode = mPositionMode;
if (!pClient->startTracking(locationOption)) {
LOC_LOGe("Failed to start session");
return;
}
// success
pClient->mTracking = true;
pClient->mPendingMessages.push(E_LOCAPI_START_TRACKING_MSG_ID);
LOC_LOGi(">-- start started session");
return;
}
void LocationApiService::stopTracking(LocAPIStopTrackingReqMsg *pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (!pClient) {
LOC_LOGe(">-- stop invlalid client=%s", pMsg->mSocketName);
return;
}
pClient->mTracking = false;
pClient->unsubscribeLocationSessionCb();
pClient->stopTracking();
pClient->mPendingMessages.push(E_LOCAPI_STOP_TRACKING_MSG_ID);
LOC_LOGi(">-- stopping session");
}
// no need to hold the lock as lock has been held on calling functions
void LocationApiService::suspendAllTrackingSessions() {
for (auto client : mClients) {
// stop session if running
if (client.second && client.second->mTracking) {
client.second->stopTracking();
client.second->mPendingMessages.push(E_LOCAPI_STOP_TRACKING_MSG_ID);
LOC_LOGi("--> suspended");
}
}
}
// no need to hold the lock as lock has been held on calling functions
void LocationApiService::resumeAllTrackingSessions() {
for (auto client : mClients) {
// start session if not running
if (client.second && client.second->mTracking) {
// resume session with preserved options
if (!client.second->startTracking()) {
LOC_LOGe("Failed to start session");
return;
}
// success
client.second->mPendingMessages.push(E_LOCAPI_START_TRACKING_MSG_ID);
LOC_LOGi("--> resumed");
}
}
}
void LocationApiService::updateSubscription(LocAPIUpdateCallbacksReqMsg *pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (!pClient) {
LOC_LOGe(">-- updateSubscription invlalid client=%s", pMsg->mSocketName);
return;
}
pClient->updateSubscription(pMsg->locationCallbacks);
LOC_LOGi(">-- update subscription client=%s mask=0x%x",
pMsg->mSocketName, pMsg->locationCallbacks);
}
void LocationApiService::updateTrackingOptions(LocAPIUpdateTrackingOptionsReqMsg *pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (pClient) {
LocationOptions locationOption = pMsg->locOptions;
// set the mode according to the master position mode
locationOption.mode = mPositionMode;
pClient->updateTrackingOptions(locationOption);
pClient->mPendingMessages.push(E_LOCAPI_UPDATE_TRACKING_OPTIONS_MSG_ID);
}
LOC_LOGi(">-- update tracking options");
}
void LocationApiService::updateNetworkAvailability(bool availability) {
LOC_LOGi(">-- updateNetworkAvailability=%u", availability);
std::string apn("");
GnssInterface* gnssInterface = getGnssInterface();
if (gnssInterface) {
// Map the network connectivity to MOBILE for now.
// In next phase, when we support third party connectivity manager,
// we plan to deplicate this API.
gnssInterface->updateConnectionStatus(
availability, loc_core::TYPE_MOBILE, false, NETWORK_HANDLE_UNKNOWN, apn);
}
}
void LocationApiService::getGnssEnergyConsumed(const char* clientSocketName) {
LOC_LOGi(">-- getGnssEnergyConsumed by=%s", clientSocketName);
GnssInterface* gnssInterface = getGnssInterface();
if (!gnssInterface) {
LOC_LOGe(">-- getGnssEnergyConsumed null GnssInterface");
return;
}
std::lock_guard<std::mutex> lock(mMutex);
bool requestAlreadyPending = false;
for (auto each : mClients) {
if ((each.second != nullptr) &&
(each.second->hasPendingEngineInfoRequest(E_ENGINE_INFO_CB_GNSS_ENERGY_CONSUMED_BIT))) {
requestAlreadyPending = true;
break;
}
}
std::string clientname(clientSocketName);
LocHalDaemonClientHandler* pClient = getClient(clientname);
if (pClient) {
pClient->addEngineInfoRequst(E_ENGINE_INFO_CB_GNSS_ENERGY_CONSUMED_BIT);
// this is first client coming to request GNSS energy consumed
if (requestAlreadyPending == false) {
LOC_LOGd("--< issue request to GNSS HAL");
// callback function when gpss engine report back energy consumed info
GnssEnergyConsumedCallback reportEnergyCb =
[this](uint64_t total) {
onGnssEnergyConsumedCb(total);
};
gnssInterface->getGnssEnergyConsumed(reportEnergyCb);
}
}
}
void LocationApiService::getConstellationSecondaryBandConfig(
const LocConfigGetConstellationSecondaryBandConfigReqMsg* pReqMsg) {
LOC_LOGi(">--getConstellationConfig");
GnssInterface* gnssInterface = getGnssInterface();
if (!gnssInterface) {
LOC_LOGe(">-- null GnssInterface");
return;
}
std::lock_guard<std::mutex> lock(mMutex);
// retrieve the constellation enablement/disablement config
// blacklisted SV info and secondary band config
uint32_t sessionId = gnssInterface-> gnssGetSecondaryBandConfig();
// if sessionId is 0, e.g.: error callback will be delivered
// by addConfigRequestToMap
addConfigRequestToMap(sessionId, pReqMsg);
}
/******************************************************************************
LocationApiService - implementation - batching
******************************************************************************/
void LocationApiService::startBatching(LocAPIStartBatchingReqMsg *pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (!pClient) {
LOC_LOGe(">-- start invalid client=%s", pMsg->mSocketName);
return;
}
if (!pClient->startBatching(pMsg->intervalInMs, pMsg->distanceInMeters,
pMsg->batchingMode)) {
LOC_LOGe("Failed to start session");
return;
}
// success
pClient->mBatching = true;
pClient->mBatchingMode = pMsg->batchingMode;
pClient->mPendingMessages.push(E_LOCAPI_START_BATCHING_MSG_ID);
LOC_LOGi(">-- start batching session");
return;
}
void LocationApiService::stopBatching(LocAPIStopBatchingReqMsg *pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (!pClient) {
LOC_LOGe(">-- stop invalid client=%s", pMsg->mSocketName);
return;
}
pClient->mBatching = false;
pClient->mBatchingMode = BATCHING_MODE_NO_AUTO_REPORT;
pClient->updateSubscription(0);
pClient->stopBatching();
pClient->mPendingMessages.push(E_LOCAPI_STOP_BATCHING_MSG_ID);
LOC_LOGi(">-- stopping batching session");
}
void LocationApiService::updateBatchingOptions(LocAPIUpdateBatchingOptionsReqMsg *pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (pClient) {
pClient->updateBatchingOptions(pMsg->intervalInMs, pMsg->distanceInMeters,
pMsg->batchingMode);
pClient->mPendingMessages.push(E_LOCAPI_UPDATE_BATCHING_OPTIONS_MSG_ID);
}
LOC_LOGi(">-- update batching options");
}
/******************************************************************************
LocationApiService - implementation - geofence
******************************************************************************/
void LocationApiService::addGeofences(LocAPIAddGeofencesReqMsg* pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (!pClient) {
LOC_LOGe(">-- start invlalid client=%s", pMsg->mSocketName);
return;
}
if (pMsg->geofences.count > MAX_GEOFENCE_COUNT) {
LOC_LOGe(">-- geofence count greater than MAX =%d", pMsg->geofences.count);
return;
}
GeofenceOption* gfOptions =
(GeofenceOption*)malloc(pMsg->geofences.count * sizeof(GeofenceOption));
GeofenceInfo* gfInfos = (GeofenceInfo*)malloc(pMsg->geofences.count * sizeof(GeofenceInfo));
uint32_t* clientIds = (uint32_t*)malloc(pMsg->geofences.count * sizeof(uint32_t));
if ((nullptr == gfOptions) || (nullptr == gfInfos) || (nullptr == clientIds)) {
LOC_LOGe("Failed to malloc memory!");
if (clientIds != nullptr) {
free(clientIds);
}
if (gfInfos != nullptr) {
free(gfInfos);
}
if (gfOptions != nullptr) {
free(gfOptions);
}
return;
}
for(int i=0; i < pMsg->geofences.count; ++i) {
gfOptions[i] = pMsg->geofences.gfPayload[i].gfOption;
gfInfos[i] = pMsg->geofences.gfPayload[i].gfInfo;
clientIds[i] = pMsg->geofences.gfPayload[i].gfClientId;
}
uint32_t* sessions = pClient->addGeofences(pMsg->geofences.count, gfOptions, gfInfos);
if (!sessions) {
LOC_LOGe("Failed to add geofences");
free(clientIds);
free(gfInfos);
free(gfOptions);
return;
}
pClient->setGeofenceIds(pMsg->geofences.count, clientIds, sessions);
// success
pClient->mGfPendingMessages.push(E_LOCAPI_ADD_GEOFENCES_MSG_ID);
LOC_LOGi(">-- add geofences");
free(clientIds);
free(gfInfos);
free(gfOptions);
}
void LocationApiService::removeGeofences(LocAPIRemoveGeofencesReqMsg* pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (nullptr == pClient) {
LOC_LOGe("removeGeofences - Null client!");
return;
}
uint32_t* sessions = pClient->getSessionIds(pMsg->gfClientIds.count, pMsg->gfClientIds.gfIds);
if (pClient && sessions) {
pClient->removeGeofences(pMsg->gfClientIds.count, sessions);
pClient->mGfPendingMessages.push(E_LOCAPI_REMOVE_GEOFENCES_MSG_ID);
}
LOC_LOGi(">-- remove geofences");
free(sessions);
}
void LocationApiService::modifyGeofences(LocAPIModifyGeofencesReqMsg* pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (nullptr == pClient) {
LOC_LOGe("modifyGeofences - Null client!");
return;
}
if (pMsg->geofences.count > MAX_GEOFENCE_COUNT) {
LOC_LOGe("modifyGeofences - geofence count greater than MAX =%d", pMsg->geofences.count);
return;
}
GeofenceOption* gfOptions = (GeofenceOption*)
malloc(sizeof(GeofenceOption) * pMsg->geofences.count);
uint32_t* clientIds = (uint32_t*)malloc(sizeof(uint32_t) * pMsg->geofences.count);
if (nullptr == gfOptions || nullptr == clientIds) {
LOC_LOGe("Failed to malloc memory!");
if (clientIds != nullptr) {
free(clientIds);
}
if (gfOptions != nullptr) {
free(gfOptions);
}
return;
}
for (int i=0; i<pMsg->geofences.count; ++i) {
gfOptions[i] = pMsg->geofences.gfPayload[i].gfOption;
clientIds[i] = pMsg->geofences.gfPayload[i].gfClientId;
}
uint32_t* sessions = pClient->getSessionIds(pMsg->geofences.count, clientIds);
if (pClient && sessions) {
pClient->modifyGeofences(pMsg->geofences.count, sessions, gfOptions);
pClient->mGfPendingMessages.push(E_LOCAPI_MODIFY_GEOFENCES_MSG_ID);
}
LOC_LOGi(">-- modify geofences");
free(sessions);
free(clientIds);
free(gfOptions);
}
void LocationApiService::pauseGeofences(LocAPIPauseGeofencesReqMsg* pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (nullptr == pClient) {
LOC_LOGe("pauseGeofences - Null client!");
return;
}
uint32_t* sessions = pClient->getSessionIds(pMsg->gfClientIds.count, pMsg->gfClientIds.gfIds);
if (pClient && sessions) {
pClient->pauseGeofences(pMsg->gfClientIds.count, sessions);
pClient->mGfPendingMessages.push(E_LOCAPI_PAUSE_GEOFENCES_MSG_ID);
}
LOC_LOGi(">-- pause geofences");
free(sessions);
}
void LocationApiService::resumeGeofences(LocAPIResumeGeofencesReqMsg* pMsg) {
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (nullptr == pClient) {
LOC_LOGe("resumeGeofences - Null client!");
return;
}
uint32_t* sessions = pClient->getSessionIds(pMsg->gfClientIds.count, pMsg->gfClientIds.gfIds);
if (pClient && sessions) {
pClient->resumeGeofences(pMsg->gfClientIds.count, sessions);
pClient->mGfPendingMessages.push(E_LOCAPI_RESUME_GEOFENCES_MSG_ID);
}
LOC_LOGi(">-- resume geofences");
free(sessions);
}
void LocationApiService::pingTest(LocAPIPingTestReqMsg* pMsg) {
// test only - ignore this request when config is not enabled
std::lock_guard<std::mutex> lock(mMutex);
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (!pClient) {
LOC_LOGe(">-- pingTest invlalid client=%s", pMsg->mSocketName);
return;
}
pClient->pingTest();
LOC_LOGd(">-- pingTest");
}
void LocationApiService::configConstrainedTunc(
const LocConfigConstrainedTuncReqMsg* pMsg){
if (!pMsg) {
return;
}
std::lock_guard<std::mutex> lock(mMutex);
uint32_t sessionId = mLocationControlApi->configConstrainedTimeUncertainty(
pMsg->mEnable, pMsg->mTuncConstraint, pMsg->mEnergyBudget);
LOC_LOGi(">-- enable: %d, tunc constraint %f, energy budget %d, session ID = %d",
pMsg->mEnable, pMsg->mTuncConstraint, pMsg->mEnergyBudget,
sessionId);
addConfigRequestToMap(sessionId, pMsg);
}
void LocationApiService::configPositionAssistedClockEstimator(
const LocConfigPositionAssistedClockEstimatorReqMsg* pMsg)
{
std::lock_guard<std::mutex> lock(mMutex);
if (!pMsg || !mLocationControlApi) {
return;
}
uint32_t sessionId = mLocationControlApi->
configPositionAssistedClockEstimator(pMsg->mEnable);
LOC_LOGi(">-- enable: %d, session ID = %d", pMsg->mEnable, sessionId);
addConfigRequestToMap(sessionId, pMsg);
}
void LocationApiService::configConstellations(const LocConfigSvConstellationReqMsg* pMsg) {
if (!pMsg) {
return;
}
std::lock_guard<std::mutex> lock(mMutex);
uint32_t sessionId = mLocationControlApi->configConstellations(
pMsg->mConstellationEnablementConfig, pMsg->mBlacklistSvConfig);
LOC_LOGi(">-- reset sv type config: %d, enable constellations: 0x%" PRIx64 ", "
"blacklisted consteallations: 0x%" PRIx64 ", ",
(pMsg->mConstellationEnablementConfig.size == 0),
pMsg->mConstellationEnablementConfig.enabledSvTypesMask,
pMsg->mConstellationEnablementConfig.blacklistedSvTypesMask);
addConfigRequestToMap(sessionId, pMsg);
}
void LocationApiService::configConstellationSecondaryBand(
const LocConfigConstellationSecondaryBandReqMsg* pMsg) {
if (!pMsg) {
return;
}
std::lock_guard<std::mutex> lock(mMutex);
uint32_t sessionId = mLocationControlApi->configConstellationSecondaryBand(
pMsg->mSecondaryBandConfig);
LOC_LOGi(">-- secondary band size %d, enabled constellation: 0x%" PRIx64 ", "
"secondary band disabed constellation: 0x%" PRIx64 "",
pMsg->mSecondaryBandConfig.size,
pMsg->mSecondaryBandConfig.enabledSvTypesMask,
pMsg->mSecondaryBandConfig.blacklistedSvTypesMask);
addConfigRequestToMap(sessionId, pMsg);
}
void LocationApiService::configAidingDataDeletion(LocConfigAidingDataDeletionReqMsg* pMsg) {
if (!pMsg) {
return;
}
std::lock_guard<std::mutex> lock(mMutex);
LOC_LOGi(">-- client %s, deleteAll %d",
pMsg->mSocketName, pMsg->mAidingData.deleteAll);
// suspend all sessions before calling delete
suspendAllTrackingSessions();
uint32_t sessionId = mLocationControlApi->gnssDeleteAidingData(pMsg->mAidingData);
addConfigRequestToMap(sessionId, pMsg);
#ifdef POWERMANAGER_ENABLED
// We do not need to resume the session if device is suspend/shutdown state
// as sessions will resumed when power state changes to resume
if ((POWER_STATE_SUSPEND == mPowerState) ||
(POWER_STATE_SHUTDOWN == mPowerState)) {
return;
}
#endif
// resume all sessions after calling aiding data deletion
resumeAllTrackingSessions();
}
void LocationApiService::configLeverArm(const LocConfigLeverArmReqMsg* pMsg){
if (!pMsg) {
return;
}
std::lock_guard<std::mutex> lock(mMutex);
uint32_t sessionId = mLocationControlApi->configLeverArm(pMsg->mLeverArmConfigInfo);
addConfigRequestToMap(sessionId, pMsg);
}
void LocationApiService::configRobustLocation(const LocConfigRobustLocationReqMsg* pMsg){
if (!pMsg) {
return;
}
std::lock_guard<std::mutex> lock(mMutex);
LOC_LOGi(">-- client %s, enable %d, enableForE911 %d",
pMsg->mSocketName, pMsg->mEnable, pMsg->mEnableForE911);
uint32_t sessionId = mLocationControlApi->configRobustLocation(
pMsg->mEnable, pMsg->mEnableForE911);
addConfigRequestToMap(sessionId, pMsg);
}
void LocationApiService::configMinGpsWeek(const LocConfigMinGpsWeekReqMsg* pMsg){
if (!pMsg) {
return;
}
std::lock_guard<std::mutex> lock(mMutex);
LOC_LOGi(">-- client %s, minGpsWeek %u",
pMsg->mSocketName, pMsg->mMinGpsWeek);
uint32_t sessionId =
mLocationControlApi->configMinGpsWeek(pMsg->mMinGpsWeek);
addConfigRequestToMap(sessionId, pMsg);
}
void LocationApiService::configMinSvElevation(const LocConfigMinSvElevationReqMsg* pMsg){
if (!pMsg) {
return;
}
std::lock_guard<std::mutex> lock(mMutex);
LOC_LOGi(">-- client %s, minSvElevation %u", pMsg->mSocketName, pMsg->mMinSvElevation);
GnssConfig gnssConfig = {};
gnssConfig.flags = GNSS_CONFIG_FLAGS_MIN_SV_ELEVATION_BIT;
gnssConfig.minSvElevation = pMsg->mMinSvElevation;
uint32_t sessionId = gnssUpdateConfig(gnssConfig);
addConfigRequestToMap(sessionId, pMsg);
}
void LocationApiService::configEngineRunState(const LocConfigEngineRunStateReqMsg* pMsg) {
if (!pMsg) {
return;
}
std::lock_guard<std::mutex> lock(mMutex);
LOC_LOGi(">-- client %s, eng type 0x%x, eng state %d",
pMsg->mSocketName, pMsg->mEngType, pMsg->mEngState);
uint32_t sessionId =
mLocationControlApi->configEngineRunState(pMsg->mEngType, pMsg->mEngState);
addConfigRequestToMap(sessionId, pMsg);
}
void LocationApiService::configUserConsentTerrestrialPositioning(
LocConfigUserConsentTerrestrialPositioningReqMsg* pMsg) {
if (!pMsg) {
return;
}
std::lock_guard<std::mutex> lock(mMutex);
LOC_LOGi(">-- client %s, current user consent %d, new usr consent %d",
pMsg->mSocketName, mOptInTerrestrialService, pMsg->mUserConsent);
mOptInTerrestrialService = pMsg->mUserConsent;
if ((mOptInTerrestrialService == true) && (mGtpWwanSsLocationApi == nullptr)) {
// set callback functions for Location API
mGtpWwanSsLocationApiCallbacks.size = sizeof(mGtpWwanSsLocationApiCallbacks);
// mandatory callback
mGtpWwanSsLocationApiCallbacks.capabilitiesCb = [this](LocationCapabilitiesMask mask) {
onCapabilitiesCallback(mask);
};
mGtpWwanSsLocationApiCallbacks.responseCb = [this](LocationError err, uint32_t id) {
onResponseCb(err, id);
};
mGtpWwanSsLocationApiCallbacks.collectiveResponseCb =
[this](size_t count, LocationError* errs, uint32_t* ids) {
onCollectiveResponseCallback(count, errs, ids);
};
mGtpWwanPosCallback = [this](Location location) {
onGtpWwanTrackingCallback(location);
};
mGtpWwanSsLocationApi = LocationAPI::createInstance(mGtpWwanSsLocationApiCallbacks);
if (mGtpWwanSsLocationApi) {
mGtpWwanSsLocationApi->enableNetworkProvider();
}
}
uint32_t sessionId = mLocationControlApi->setOptInStatus(pMsg->mUserConsent);
addConfigRequestToMap(sessionId, pMsg);
}
void LocationApiService::getGnssConfig(const LocAPIMsgHeader* pReqMsg,
GnssConfigFlagsBits configFlag) {
std::lock_guard<std::mutex> lock(mMutex);
if (!pReqMsg) {
return;
}
uint32_t sessionId = 0;
uint32_t* sessionIds = mLocationControlApi->gnssGetConfig(
configFlag);
if (sessionIds) {
LOC_LOGd(">-- session id %d", *sessionIds);
sessionId = *sessionIds;
// free the memory used by sessionIds
delete[] sessionIds;
}
// if sessionId is 0, e.g.: error callback will be delivered
// by addConfigRequestToMap
addConfigRequestToMap(sessionId, pReqMsg);
}
void LocationApiService::configDeadReckoningEngineParams(const LocConfigDrEngineParamsReqMsg* pMsg){
if (!pMsg) {
return;
}
std::lock_guard<std::mutex> lock(mMutex);
uint32_t sessionId = mLocationControlApi->configDeadReckoningEngineParams(
pMsg->mDreConfig);
addConfigRequestToMap(sessionId, pMsg);
}
void LocationApiService::addConfigRequestToMap(
uint32_t sessionId, const LocAPIMsgHeader* pMsg){
// for config request that is invoked from location integration API
// if session id is valid, we need to add it to the map so when response
// comes back, we can deliver the response to the integration api client
if (sessionId != 0) {
ConfigReqClientData configClientData;
configClientData.configMsgId = pMsg->msgId;
configClientData.clientName = pMsg->mSocketName;
mConfigReqs.emplace(sessionId, configClientData);
} else {
// if session id is 0, we need to deliver failed response back to the
// client
LocHalDaemonClientHandler* pClient = getClient(pMsg->mSocketName);
if (pClient) {
pClient->onControlResponseCb(LOCATION_ERROR_GENERAL_FAILURE, pMsg->msgId);
}
}
}
/******************************************************************************
LocationApiService - Location Control API callback functions
******************************************************************************/
void LocationApiService::onControlResponseCallback(LocationError err, uint32_t sessionId) {
std::lock_guard<std::mutex> lock(mMutex);
LOC_LOGd("--< onControlResponseCallback err=%u id=%u", err, sessionId);
auto configReqData = mConfigReqs.find(sessionId);
if (configReqData != std::end(mConfigReqs)) {
LocHalDaemonClientHandler* pClient = getClient(configReqData->second.clientName);
if (pClient) {
pClient->onControlResponseCb(err, configReqData->second.configMsgId);
}
mConfigReqs.erase(configReqData);
LOC_LOGd("--< map size %d", mConfigReqs.size());
} else {
LOC_LOGe("--< client not found for session id %d", sessionId);
}
}
void LocationApiService::onControlCollectiveResponseCallback(
size_t count, LocationError *errs, uint32_t *ids) {
std::lock_guard<std::mutex> lock(mMutex);
if (count != 1) {
LOC_LOGe("--< onControlCollectiveResponseCallback, count is %d, expecting 1", count);
return;
}
uint32_t sessionId = *ids;
LocationError err = *errs;
LOC_LOGd("--< onControlCollectiveResponseCallback, session id is %d, err is %d",
sessionId, err);
// as we only update one setting at a time, we only need to process
// the first id
auto configReqData = mConfigReqs.find(sessionId);
if (configReqData != std::end(mConfigReqs)) {
LocHalDaemonClientHandler* pClient = getClient(configReqData->second.clientName.c_str());
if (pClient) {
pClient->onControlResponseCb(err, configReqData->second.configMsgId);
}
mConfigReqs.erase(configReqData);
LOC_LOGd("--< map size %d", mConfigReqs.size());
} else {
LOC_LOGe("--< client not found for session id %d", sessionId);
}
}
void LocationApiService::onGnssConfigCallback(uint32_t sessionId,
const GnssConfig& config) {
std::lock_guard<std::mutex> lock(mMutex);
LOC_LOGd("--< onGnssConfigCallback, req cnt %d", mConfigReqs.size());
auto configReqData = mConfigReqs.find(sessionId);
if (configReqData != std::end(mConfigReqs)) {
LocHalDaemonClientHandler* pClient = getClient(configReqData->second.clientName);
if (pClient) {
// invoke the respCb to deliver success status
pClient->onControlResponseCb(LOCATION_ERROR_SUCCESS, configReqData->second.configMsgId);
// invoke the configCb to deliver the config
pClient->onGnssConfigCb(configReqData->second.configMsgId, config);
}
mConfigReqs.erase(configReqData);
LOC_LOGd("--< map size %d", mConfigReqs.size());
} else {
LOC_LOGe("--< client not found for session id %d", sessionId);
}
}
// mandatory callback for location api
void LocationApiService::onCapabilitiesCallback(LocationCapabilitiesMask mask) {
}
// mandatory callback for location api
void LocationApiService::onResponseCb(LocationError err, uint32_t id) {
}
// mandatory callback for location api
void LocationApiService::onCollectiveResponseCallback(
size_t count, LocationError *errs, uint32_t *ids) {
}
void LocationApiService::onGtpWwanTrackingCallback(Location location) {
std::lock_guard<std::mutex> lock(mMutex);
LOC_LOGd("--< onGtpWwanTrackingCallback optIn=%u loc flags=0x%x", mOptInTerrestrialService,
location.flags);
if ((mTerrestrialFixReqs.size() != 0) &&
(location.flags & LOCATION_HAS_LAT_LONG_BIT) && (mOptInTerrestrialService == 1)) {
for (auto it = mTerrestrialFixReqs.begin(); it != mTerrestrialFixReqs.end();) {
LocHalDaemonClientHandler* pClient = getClient(it->first);
pClient->sendTerrestrialFix(LOCATION_ERROR_SUCCESS, location);
++it;
}
mTerrestrialFixReqs.clear();
mGtpWwanSsLocationApi->stopNetworkLocation(&mGtpWwanPosCallback);
}
}
/******************************************************************************
LocationApiService - power event handlers
******************************************************************************/
#ifdef POWERMANAGER_ENABLED
void LocationApiService::onPowerEvent(PowerStateType powerState) {
std::lock_guard<std::mutex> lock(mMutex);
LOC_LOGd("--< onPowerEvent %d", powerState);
mPowerState = powerState;
if ((POWER_STATE_SUSPEND == powerState) ||
(POWER_STATE_SHUTDOWN == powerState)) {
suspendAllTrackingSessions();
} else if (POWER_STATE_RESUME == powerState) {
resumeAllTrackingSessions();
}
GnssInterface* gnssInterface = getGnssInterface();
if (!gnssInterface) {
LOC_LOGe(">-- getGnssEnergyConsumed null GnssInterface");
return;
}
gnssInterface->updateSystemPowerState(powerState);
}
#endif
/******************************************************************************
LocationApiService - on query callback from location engines
******************************************************************************/
void LocationApiService::onGnssEnergyConsumedCb(uint64_t totalGnssEnergyConsumedSinceFirstBoot) {
std::lock_guard<std::mutex> lock(mMutex);
LOC_LOGd("--< onGnssEnergyConsumedCb");
LocAPIGnssEnergyConsumedIndMsg msg(SERVICE_NAME, totalGnssEnergyConsumedSinceFirstBoot,
&mPbufMsgConv);
for (auto each : mClients) {
// deliver the engergy info to registered client
each.second->onGnssEnergyConsumedInfoAvailable(msg);
}
}
/******************************************************************************
LocationApiService - other utilities
******************************************************************************/
GnssInterface* LocationApiService::getGnssInterface() {
static bool getGnssInterfaceFailed = false;
static GnssInterface* gnssInterface = nullptr;
if (nullptr == gnssInterface && !getGnssInterfaceFailed) {
void * tempPtr = nullptr;
getLocationInterface* getter = (getLocationInterface*)
dlGetSymFromLib(tempPtr, "libgnss.so", "getGnssInterface");
if (nullptr == getter) {
getGnssInterfaceFailed = true;
} else {
gnssInterface = (GnssInterface*)(*getter)();
}
}
return gnssInterface;
}
void LocationApiService::performMaintenance() {
ClientNameIpcSenderMap clientsToCheck;
// Hold the lock when we access global variable of mClients
// copy out the client name and shared_ptr of ipc sender for the clients.
// We do not use mClients directly or making a copy of mClients, as the
// client handler object can become invalid when the client gets
// deleted by the thread of LocationApiService.
{
std::lock_guard<std::mutex> lock(mMutex);
for (auto client : mClients) {
if (client.first.compare(AUTO_START_CLIENT_NAME) != 0) {
clientsToCheck.emplace(client.first, client.second->getIpcSender());
}
}
}
for (auto client : clientsToCheck) {
string pbStr;
bool messageSent = false;
LocAPIPingTestReqMsg msg(SERVICE_NAME, &mPbufMsgConv);
if (msg.serializeToProtobuf(pbStr)) {
messageSent = LocIpc::send(*client.second,
reinterpret_cast<uint8_t *>((uint8_t *)pbStr.c_str()), pbStr.size());
} else {
LOC_LOGe("LocAPIPingTestReqMsg serializeToProtobuf failed");
}
LOC_LOGd("send ping message returned %d for client %s", messageSent, client.first.c_str());
if (messageSent == false) {
LOC_LOGe("--< ping failed for client %s", client.first.c_str());
deleteClientbyName(client.first);
}
}
// after maintenace, start next timer
mMaintTimer.start(MAINT_TIMER_INTERVAL_MSEC, false);
}
// Maintenance timer to clean up resources when client exists without sending
// out de-registration message
void MaintTimer::timeOutCallback() {
LOC_LOGd("maint timer fired");
struct PerformMaintenanceReq : public LocMsg {
PerformMaintenanceReq(LocationApiService* locationApiService) :
mLocationApiService(locationApiService){}
virtual ~PerformMaintenanceReq() {}
void proc() const {
mLocationApiService->performMaintenance();
}
LocationApiService* mLocationApiService;
};
mLocationApiService->getMsgTask().sendMsg(new PerformMaintenanceReq(mLocationApiService));
}
/******************************************************************************
LocationApiService - GTP WWAN functionality
******************************************************************************/
void LocationApiService::getSingleTerrestrialPos(
LocAPIGetSingleTerrestrialPosReqMsg* pReqMsg) {
std::string clientName(pReqMsg->mSocketName);
LOC_LOGd(">--getSingleTerrestrialPos, timeout msec %d, tech mask 0x%x, horQoS %f",
pReqMsg->mTimeoutMsec, pReqMsg->mTechMask, pReqMsg->mHorQoS);
std::lock_guard<std::mutex> lock(mMutex);
// Make sure client has opt-in for the service
if (mOptInTerrestrialService != 1) {
LocHalDaemonClientHandler* pClient = getClient(clientName);
if (pClient) {
// inform client that GTP service is not supported
Location location = {};
pClient->sendTerrestrialFix(LOCATION_ERROR_NOT_SUPPORTED, location);
}
} else {
mTerrestrialFixReqs.emplace(std::piecewise_construct,
std::forward_as_tuple(clientName),
std::forward_as_tuple(this, clientName));
auto it = mTerrestrialFixReqs.find(clientName);
if (it != mTerrestrialFixReqs.end()) {
it->second.start(pReqMsg->mTimeoutMsec, false);
}
if (mTerrestrialFixReqs.size() == 1) {
mGtpWwanSsLocationApi->startNetworkLocation(&mGtpWwanPosCallback);
}
}
}
void LocationApiService::gtpFixRequestTimeout(const std::string& clientName) {
std::lock_guard<std::mutex> lock(LocationApiService::mMutex);
LOC_LOGd("timer out processing for client %s", clientName.c_str());
auto it = mTerrestrialFixReqs.find(clientName);
if (it != mTerrestrialFixReqs.end()) {
LocHalDaemonClientHandler* pClient = getClient(clientName);
if (pClient) {
// inform client of timeout
Location location = {};
pClient->sendTerrestrialFix(LOCATION_ERROR_TIMEOUT, location);
}
mTerrestrialFixReqs.erase(clientName);
// stop tracking if there is no more request
if (mTerrestrialFixReqs.size() == 1) {
mGtpWwanSsLocationApi->stopNetworkLocation(&mGtpWwanPosCallback);
}
}
}
void SingleTerrestrialFixTimer::timeOutCallback() {
LOC_LOGd("SingleTerrestrialFix timeout timer fired");
struct SingleTerrestrialFixTimeoutReq : public LocMsg {
SingleTerrestrialFixTimeoutReq(LocationApiService* locationApiService,
const std::string &clientName) :
mLocationApiService(locationApiService),
mClientName(clientName) {}
virtual ~SingleTerrestrialFixTimeoutReq() {}
void proc() const {
mLocationApiService->gtpFixRequestTimeout(mClientName);
}
LocationApiService* mLocationApiService;
std::string mClientName;
};
mLocationApiService->getMsgTask().sendMsg(new SingleTerrestrialFixTimeoutReq(
mLocationApiService, mClientName));
}