diff options
Diffstat (limited to 'gps/gnss/GnssAdapter.cpp')
-rw-r--r-- | gps/gnss/GnssAdapter.cpp | 3323 |
1 files changed, 0 insertions, 3323 deletions
diff --git a/gps/gnss/GnssAdapter.cpp b/gps/gnss/GnssAdapter.cpp deleted file mode 100644 index 6df8e12..0000000 --- a/gps/gnss/GnssAdapter.cpp +++ /dev/null @@ -1,3323 +0,0 @@ -/* Copyright (c) 2017, 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_TAG "LocSvc_GnssAdapter" - -#include <inttypes.h> -#include <sys/stat.h> -#include <errno.h> -#include <ctype.h> -#include <cutils/properties.h> -#include <math.h> -#include <arpa/inet.h> -#include <netinet/in.h> -#include <netdb.h> -#include <GnssAdapter.h> -#include <string> -#include <loc_log.h> -#include <loc_nmea.h> -#include <Agps.h> -#include <SystemStatus.h> - -#include <vector> - -#define RAD2DEG (180.0 / M_PI) - -using namespace loc_core; - -/* Method to fetch status cb from loc_net_iface library */ -typedef AgpsCbInfo& (*LocAgpsGetAgpsCbInfo)(LocAgpsOpenResultCb openResultCb, - LocAgpsCloseResultCb closeResultCb, void* userDataPtr); - -static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn, - AGpsBearerType bearerType, void* userDataPtr); -static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr); - -GnssAdapter::GnssAdapter() : - LocAdapterBase(0, - LocDualContext::getLocFgContext(NULL, - NULL, - LocDualContext::mLocationHalName, - false)), - mUlpProxy(new UlpProxyBase()), - mUlpPositionMode(), - mGnssSvIdUsedInPosition(), - mGnssSvIdUsedInPosAvail(false), - mControlCallbacks(), - mPowerVoteId(0), - mNmeaMask(0), - mNiData(), - mAgpsManager(), - mAgpsCbInfo(), - mOdcpiRequestCb(nullptr), - mOdcpiRequestActive(false), - mOdcpiTimer(this), - mOdcpiRequest(), - mSystemStatus(SystemStatus::getInstance(mMsgTask)), - mServerUrl(":"), - mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask) -{ - LOC_LOGD("%s]: Constructor %p", __func__, this); - mUlpPositionMode.mode = LOC_POSITION_MODE_INVALID; - - pthread_condattr_t condAttr; - pthread_condattr_init(&condAttr); - pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC); - pthread_cond_init(&mNiData.session.tCond, &condAttr); - pthread_cond_init(&mNiData.sessionEs.tCond, &condAttr); - pthread_condattr_destroy(&condAttr); - - /* Set ATL open/close callbacks */ - AgpsAtlOpenStatusCb atlOpenStatusCb = - [this](int handle, int isSuccess, char* apn, - AGpsBearerType bearerType, AGpsExtType agpsType) { - - mLocApi->atlOpenStatus( - handle, isSuccess, apn, bearerType, agpsType); - }; - AgpsAtlCloseStatusCb atlCloseStatusCb = - [this](int handle, int isSuccess) { - - mLocApi->atlCloseStatus(handle, isSuccess); - }; - - /* Register DS Client APIs */ - AgpsDSClientInitFn dsClientInitFn = - [this](bool isDueToSSR) { - - return mLocApi->initDataServiceClient(isDueToSSR); - }; - - AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn = - [this] { - - return mLocApi->openAndStartDataCall(); - }; - - AgpsDSClientStopDataCallFn dsClientStopDataCallFn = - [this] { - - mLocApi->stopDataCall(); - }; - - AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn = - [this] { - - mLocApi->closeDataCall(); - }; - - AgpsDSClientReleaseFn dsClientReleaseFn = - [this] { - - mLocApi->releaseDataServiceClient(); - }; - - /* Send Msg function */ - SendMsgToAdapterMsgQueueFn sendMsgFn = - [this](LocMsg* msg) { - - sendMsg(msg); - }; - mAgpsManager.registerATLCallbacks(atlOpenStatusCb, atlCloseStatusCb, - dsClientInitFn, dsClientOpenAndStartDataCallFn, dsClientStopDataCallFn, - dsClientCloseDataCallFn, dsClientReleaseFn, sendMsgFn); - - readConfigCommand(); - setConfigCommand(); - initDefaultAgpsCommand(); -} - -void -GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks) -{ - struct MsgSetControlCallbacks : public LocMsg { - GnssAdapter& mAdapter; - const LocationControlCallbacks mControlCallbacks; - inline MsgSetControlCallbacks(GnssAdapter& adapter, - LocationControlCallbacks& controlCallbacks) : - LocMsg(), - mAdapter(adapter), - mControlCallbacks(controlCallbacks) {} - inline virtual void proc() const { - mAdapter.setControlCallbacks(mControlCallbacks); - } - }; - - sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks)); -} - -void -GnssAdapter::convertOptions(LocPosMode& out, const LocationOptions& options) -{ - LocPosMode locPosMode = {}; - switch (options.mode) { - case GNSS_SUPL_MODE_MSB: - out.mode = LOC_POSITION_MODE_MS_BASED; - break; - case GNSS_SUPL_MODE_MSA: - out.mode = LOC_POSITION_MODE_MS_ASSISTED; - break; - default: - out.mode = LOC_POSITION_MODE_STANDALONE; - break; - } - out.share_position = true; - out.min_interval = options.minInterval; -} - -void -GnssAdapter::convertLocation(Location& out, const LocGpsLocation& locGpsLocation, - const GpsLocationExtended& locationExtended, - const LocPosTechMask techMask) -{ - memset(&out, 0, sizeof(Location)); - out.size = sizeof(Location); - if (LOC_GPS_LOCATION_HAS_LAT_LONG & locGpsLocation.flags) { - out.flags |= LOCATION_HAS_LAT_LONG_BIT; - out.latitude = locGpsLocation.latitude; - out.longitude = locGpsLocation.longitude; - } - if (LOC_GPS_LOCATION_HAS_ALTITUDE & locGpsLocation.flags) { - out.flags |= LOCATION_HAS_ALTITUDE_BIT; - out.altitude = locGpsLocation.altitude; - } - if (LOC_GPS_LOCATION_HAS_SPEED & locGpsLocation.flags) { - out.flags |= LOCATION_HAS_SPEED_BIT; - out.speed = locGpsLocation.speed; - } - if (LOC_GPS_LOCATION_HAS_BEARING & locGpsLocation.flags) { - out.flags |= LOCATION_HAS_BEARING_BIT; - out.bearing = locGpsLocation.bearing; - } - if (LOC_GPS_LOCATION_HAS_ACCURACY & locGpsLocation.flags) { - out.flags |= LOCATION_HAS_ACCURACY_BIT; - out.accuracy = locGpsLocation.accuracy; - } - if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) { - out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT; - out.verticalAccuracy = locationExtended.vert_unc; - } - if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) { - out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT; - out.speedAccuracy = locationExtended.speed_unc; - } - if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) { - out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT; - out.bearingAccuracy = locationExtended.bearing_unc; - } - out.timestamp = locGpsLocation.timestamp; - if (LOC_POS_TECH_MASK_SATELLITE & techMask) { - out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT; - } - if (LOC_POS_TECH_MASK_CELLID & techMask) { - out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT; - } - if (LOC_POS_TECH_MASK_WIFI & techMask) { - out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT; - } - if (LOC_POS_TECH_MASK_SENSORS & techMask) { - out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT; - } -} - -void -GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out, - const GpsLocationExtended& locationExtended) -{ - out.size = sizeof(GnssLocationInfoNotification); - if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) { - out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT; - out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel; - } - if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) { - out.flags |= GNSS_LOCATION_INFO_DOP_BIT; - out.pdop = locationExtended.pdop; - out.hdop = locationExtended.hdop; - out.vdop = locationExtended.vdop; - } - if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) { - out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT; - out.magneticDeviation = locationExtended.magneticDeviation; - } - if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) { - out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT; - switch (locationExtended.horizontal_reliability) { - case LOC_RELIABILITY_VERY_LOW: - out.horReliability = LOCATION_RELIABILITY_VERY_LOW; - break; - case LOC_RELIABILITY_LOW: - out.horReliability = LOCATION_RELIABILITY_LOW; - break; - case LOC_RELIABILITY_MEDIUM: - out.horReliability = LOCATION_RELIABILITY_MEDIUM; - break; - case LOC_RELIABILITY_HIGH: - out.horReliability = LOCATION_RELIABILITY_HIGH; - break; - default: - out.horReliability = LOCATION_RELIABILITY_NOT_SET; - break; - } - } - if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) { - out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT; - switch (locationExtended.vertical_reliability) { - case LOC_RELIABILITY_VERY_LOW: - out.verReliability = LOCATION_RELIABILITY_VERY_LOW; - break; - case LOC_RELIABILITY_LOW: - out.verReliability = LOCATION_RELIABILITY_LOW; - break; - case LOC_RELIABILITY_MEDIUM: - out.verReliability = LOCATION_RELIABILITY_MEDIUM; - break; - case LOC_RELIABILITY_HIGH: - out.verReliability = LOCATION_RELIABILITY_HIGH; - break; - default: - out.verReliability = LOCATION_RELIABILITY_NOT_SET; - break; - } - } - if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) { - out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT; - out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor; - } - if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) { - out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT; - out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor; - } - if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) { - out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT; - out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth; - } -} - -inline uint32_t -GnssAdapter::convertGpsLock(const GnssConfigGpsLock gpsLock) -{ - switch (gpsLock) { - case GNSS_CONFIG_GPS_LOCK_MO: - return 1; - case GNSS_CONFIG_GPS_LOCK_NI: - return 2; - case GNSS_CONFIG_GPS_LOCK_MO_AND_NI: - return 3; - case GNSS_CONFIG_GPS_LOCK_NONE: - default: - return 0; - } -} - -inline GnssConfigGpsLock -GnssAdapter::convertGpsLock(const uint32_t gpsLock) -{ - switch (gpsLock) { - case 1: - return GNSS_CONFIG_GPS_LOCK_MO; - case 2: - return GNSS_CONFIG_GPS_LOCK_NI; - case 3: - return GNSS_CONFIG_GPS_LOCK_MO_AND_NI; - case 0: - default: - return GNSS_CONFIG_GPS_LOCK_NONE; - } -} - -inline uint32_t -GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion) -{ - switch (suplVersion) { - case GNSS_CONFIG_SUPL_VERSION_2_0_0: - return 0x00020000; - case GNSS_CONFIG_SUPL_VERSION_2_0_2: - return 0x00020002; - case GNSS_CONFIG_SUPL_VERSION_1_0_0: - default: - return 0x00010000; - } -} - -inline GnssConfigSuplVersion -GnssAdapter::convertSuplVersion(const uint32_t suplVersion) -{ - switch (suplVersion) { - case 0x00020000: - return GNSS_CONFIG_SUPL_VERSION_2_0_0; - case 0x00020002: - return GNSS_CONFIG_SUPL_VERSION_2_0_2; - case 0x00010000: - default: - return GNSS_CONFIG_SUPL_VERSION_1_0_0; - } -} - -inline uint32_t -GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile) -{ - switch (lppProfile) { - case GNSS_CONFIG_LPP_PROFILE_USER_PLANE: - return 1; - case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE: - return 2; - case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE: - return 3; - case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE: - default: - return 0; - } -} - -inline GnssConfigLppProfile -GnssAdapter::convertLppProfile(const uint32_t lppProfile) -{ - switch (lppProfile) { - case 1: - return GNSS_CONFIG_LPP_PROFILE_USER_PLANE; - case 2: - return GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE; - case 3: - return GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE; - case 0: - default: - return GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; - } -} - -uint32_t -GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask) -{ - uint32_t mask = 0; - if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) { - mask |= (1<<0); - } - if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) { - mask |= (1<<1); - } - if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) { - mask |= (1<<2); - } - if (GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeControlPlaneMask) { - mask |= (1<<3); - } - return mask; -} - -GnssConfigLppeControlPlaneMask -GnssAdapter::convertLppeCp(const uint32_t lppeControlPlaneMask) -{ - GnssConfigLppeControlPlaneMask mask = 0; - if ((1<<0) & lppeControlPlaneMask) { - mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT; - } - if ((1<<1) & lppeControlPlaneMask) { - mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT; - } - if ((1<<2) & lppeControlPlaneMask) { - mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SRN_AP_MEASUREMENTS_BIT; - } - if ((1<<3) & lppeControlPlaneMask) { - mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_SENSOR_BARO_MEASUREMENTS_BIT; - } - return mask; -} - - -uint32_t -GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask) -{ - uint32_t mask = 0; - if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) { - mask |= (1<<0); - } - if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) { - mask |= (1<<1); - } - if (GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) { - mask |= (1<<2); - } - if (GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT & lppeUserPlaneMask) { - mask |= (1<<3); - } - return mask; -} - -GnssConfigLppeUserPlaneMask -GnssAdapter::convertLppeUp(const uint32_t lppeUserPlaneMask) -{ - GnssConfigLppeUserPlaneMask mask = 0; - if ((1<<0) & lppeUserPlaneMask) { - mask |= GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT; - } - if ((1<<1) & lppeUserPlaneMask) { - mask |= GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT; - } - if ((1<<2) & lppeUserPlaneMask) { - mask |= GNSS_CONFIG_LPPE_USER_PLANE_SRN_AP_MEASUREMENTS_BIT; - } - if ((1<<3) & lppeUserPlaneMask) { - mask |= GNSS_CONFIG_LPPE_USER_PLANE_SENSOR_BARO_MEASUREMENTS_BIT; - } - return mask; -} - -uint32_t -GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask) -{ - uint32_t mask = 0; - if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) { - mask |= (1<<0); - } - if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) { - mask |= (1<<1); - } - if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) { - mask |= (1<<2); - } - if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) { - mask |= (1<<3); - } - return mask; -} - -uint32_t -GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl) -{ - switch (emergencyPdnForEmergencySupl) { - case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES: - return 1; - case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO: - default: - return 0; - } -} - -uint32_t -GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices) -{ - switch (suplEmergencyServices) { - case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES: - return 1; - case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO: - default: - return 0; - } -} - -uint32_t -GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask) -{ - uint32_t mask = 0; - if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) { - mask |= (1<<0); - } - if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) { - mask |= (1<<1); - } - return mask; -} - -bool -GnssAdapter::resolveInAddress(const char* hostAddress, struct in_addr* inAddress) -{ - bool ret = true; - - struct hostent* hp; - hp = gethostbyname(hostAddress); - if (hp != NULL) { /* DNS OK */ - memcpy(inAddress, hp->h_addr_list[0], hp->h_length); - } else { - /* Try IP representation */ - if (inet_aton(hostAddress, inAddress) == 0) { - /* IP not valid */ - LOC_LOGE("%s]: DNS query on '%s' failed", __func__, hostAddress); - ret = false; - } - } - - return ret; -} - -void -GnssAdapter::readConfigCommand() -{ - LOC_LOGD("%s]: ", __func__); - - struct MsgReadConfig : public LocMsg { - GnssAdapter* mAdapter; - ContextBase& mContext; - inline MsgReadConfig(GnssAdapter* adapter, - ContextBase& context) : - LocMsg(), - mAdapter(adapter), - mContext(context) {} - inline virtual void proc() const { - // reads config into mContext->mGps_conf - mContext.readConfig(); - mContext.requestUlp((LocAdapterBase*)mAdapter, mContext.getCarrierCapabilities()); - } - }; - - if (mContext != NULL) { - sendMsg(new MsgReadConfig(this, *mContext)); - } -} - -LocationError -GnssAdapter::setSuplHostServer(const char* server, int port) -{ - LocationError locErr = LOCATION_ERROR_SUCCESS; - if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { - char serverUrl[MAX_URL_LEN] = {}; - int32_t length = -1; - const char noHost[] = "NONE"; - - locErr = LOCATION_ERROR_INVALID_PARAMETER; - - if ((NULL == server) || (server[0] == 0) || - (strncasecmp(noHost, server, sizeof(noHost)) == 0)) { - serverUrl[0] = '\0'; - length = 0; - } else if (port > 0) { - length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u", server, port); - } - - if (length >= 0 && strncasecmp(getServerUrl().c_str(), - serverUrl, sizeof(serverUrl)) != 0) { - setServerUrl(serverUrl); - locErr = mLocApi->setServer(serverUrl, length); - if (locErr != LOCATION_ERROR_SUCCESS) { - LOC_LOGE("%s]:Error while setting SUPL_HOST server:%s", - __func__, serverUrl); - } - } - } - return locErr; -} - -void -GnssAdapter::setConfigCommand() -{ - LOC_LOGD("%s]: ", __func__); - - struct MsgSetConfig : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - inline MsgSetConfig(GnssAdapter& adapter, - LocApiBase& api) : - LocMsg(), - mAdapter(adapter), - mApi(api) {} - inline virtual void proc() const { - if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { - mApi.setSUPLVersion(mAdapter.convertSuplVersion(ContextBase::mGps_conf.SUPL_VER)); - mApi.setLPPConfig(mAdapter.convertLppProfile(ContextBase::mGps_conf.LPP_PROFILE)); - mApi.setAGLONASSProtocol(ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT); - } - mAdapter.setSuplHostServer(ContextBase::mGps_conf.SUPL_HOST, - ContextBase::mGps_conf.SUPL_PORT); - mApi.setSensorControlConfig(ContextBase::mSap_conf.SENSOR_USAGE, - ContextBase::mSap_conf.SENSOR_PROVIDER); - mApi.setLPPeProtocolCp( - mAdapter.convertLppeCp(ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY)); - mApi.setLPPeProtocolUp( - mAdapter.convertLppeUp(ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY)); - - // set nmea mask type - uint32_t mask = 0; - if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) { - mask |= LOC_NMEA_ALL_GENERAL_SUPPORTED_MASK; - } - if (mApi.isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) { - mask |= LOC_NMEA_MASK_DEBUG_V02; - } - if (mask != 0) { - mApi.setNMEATypes(mask); - } - mAdapter.mNmeaMask= mask; - - mApi.setXtraVersionCheck(ContextBase::mGps_conf.XTRA_VERSION_CHECK); - if (ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID || - ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID || - ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID || - ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID || - ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) { - mApi.setSensorProperties( - ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID, - ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK, - ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID, - ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY, - ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, - ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY, - ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, - ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY, - ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID, - ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY); - } - mApi.setSensorPerfControlConfig( - ContextBase::mSap_conf.SENSOR_CONTROL_MODE, - ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH, - ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC, - ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH, - ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC, - ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH, - ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH, - ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH, - ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH, - ContextBase::mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK); - } - }; - - sendMsg(new MsgSetConfig(*this, *mLocApi)); -} - -uint32_t* -GnssAdapter::gnssUpdateConfigCommand(GnssConfig config) -{ - // count the number of bits set - GnssConfigFlagsMask flagsCopy = config.flags; - size_t count = 0; - while (flagsCopy > 0) { - if (flagsCopy & 1) { - count++; - } - flagsCopy >>= 1; - } - std::string idsString = "["; - uint32_t* ids = NULL; - if (count > 0) { - ids = new uint32_t[count]; - if (ids == nullptr) { - LOC_LOGE("%s] new allocation failed, fatal error.", __func__); - return nullptr; - } - for (size_t i=0; i < count; ++i) { - ids[i] = generateSessionId(); - IF_LOC_LOGD { - idsString += std::to_string(ids[i]) + " "; - } - } - } - idsString += "]"; - - LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags); - - struct MsgGnssUpdateConfig : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - GnssConfig mConfig; - uint32_t* mIds; - size_t mCount; - inline MsgGnssUpdateConfig(GnssAdapter& adapter, - LocApiBase& api, - GnssConfig config, - uint32_t* ids, - size_t count) : - LocMsg(), - mAdapter(adapter), - mApi(api), - mConfig(config), - mIds(ids), - mCount(count) {} - inline virtual ~MsgGnssUpdateConfig() - { - delete[] mIds; - } - inline virtual void proc() const { - LocationError* errs = new LocationError[mCount]; - LocationError err = LOCATION_ERROR_SUCCESS; - uint32_t index = 0; - - if (errs == nullptr) { - LOC_LOGE("%s] new allocation failed, fatal error.", __func__); - return; - } - - if (mConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) { - uint32_t newGpsLock = mAdapter.convertGpsLock(mConfig.gpsLock); - ContextBase::mGps_conf.GPS_LOCK = newGpsLock; - if (0 == mAdapter.getPowerVoteId()) { - err = mApi.setGpsLock(mConfig.gpsLock); - } - if (index < mCount) { - errs[index] = err; - } - index++; - } - if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) { - uint32_t newSuplVersion = mAdapter.convertSuplVersion(mConfig.suplVersion); - if (newSuplVersion != ContextBase::mGps_conf.SUPL_VER && - ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { - ContextBase::mGps_conf.SUPL_VER = newSuplVersion; - err = mApi.setSUPLVersion(mConfig.suplVersion); - } else { - err = LOCATION_ERROR_SUCCESS; - } - if (index < mCount) { - errs[index] = err; - } - index++; - } - if (mConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) { - if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) { - err = mAdapter.setSuplHostServer(mConfig.assistanceServer.hostName, - mConfig.assistanceServer.port); - } else if (GNSS_ASSISTANCE_TYPE_C2K == mConfig.assistanceServer.type) { - if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { - struct in_addr addr; - if (!mAdapter.resolveInAddress(mConfig.assistanceServer.hostName, - &addr)) { - LOC_LOGE("%s]: hostName %s cannot be resolved", - __func__, mConfig.assistanceServer.hostName); - err = LOCATION_ERROR_INVALID_PARAMETER; - } else { - unsigned int ip = htonl(addr.s_addr); - err = mApi.setServer(ip, mConfig.assistanceServer.port, - LOC_AGPS_CDMA_PDE_SERVER); - } - } else { - err = LOCATION_ERROR_SUCCESS; - } - } else { - LOC_LOGE("%s]: Not a valid gnss assistance type %u", - __func__, mConfig.assistanceServer.type); - err = LOCATION_ERROR_INVALID_PARAMETER; - } - if (index < mCount) { - errs[index] = err; - } - index++; - } - if (mConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) { - uint32_t newLppProfile = mAdapter.convertLppProfile(mConfig.lppProfile); - if (newLppProfile != ContextBase::mGps_conf.LPP_PROFILE && - ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { - ContextBase::mGps_conf.LPP_PROFILE = newLppProfile; - err = mApi.setLPPConfig(mConfig.lppProfile); - } else { - err = LOCATION_ERROR_SUCCESS; - } - if (index < mCount) { - errs[index] = err; - } - index++; - } - if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) { - uint32_t newLppeControlPlaneMask = - mAdapter.convertLppeCp(mConfig.lppeControlPlaneMask); - if (newLppeControlPlaneMask != ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY) { - ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask; - err = mApi.setLPPeProtocolCp(mConfig.lppeControlPlaneMask); - } else { - err = LOCATION_ERROR_SUCCESS; - } - if (index < mCount) { - errs[index] = err; - } - index++; - } - if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) { - uint32_t newLppeUserPlaneMask = - mAdapter.convertLppeUp(mConfig.lppeUserPlaneMask); - if (newLppeUserPlaneMask != ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY) { - ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask; - err = mApi.setLPPeProtocolUp(mConfig.lppeUserPlaneMask); - } else { - err = LOCATION_ERROR_SUCCESS; - } - if (index < mCount) { - errs[index] = err; - } - index++; - } - if (mConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) { - uint32_t newAGloProtMask = - mAdapter.convertAGloProt(mConfig.aGlonassPositionProtocolMask); - if (newAGloProtMask != ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT && - ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { - ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask; - err = mApi.setAGLONASSProtocol(mConfig.aGlonassPositionProtocolMask); - } else { - err = LOCATION_ERROR_SUCCESS; - } - if (index < mCount) { - errs[index] = err; - } - index++; - } - if (mConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) { - uint32_t newEP4ES = mAdapter.convertEP4ES(mConfig.emergencyPdnForEmergencySupl); - if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) { - ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES; - } - err = LOCATION_ERROR_SUCCESS; - if (index < mCount) { - errs[index] = err; - } - index++; - } - if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) { - uint32_t newSuplEs = mAdapter.convertSuplEs(mConfig.suplEmergencyServices); - if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) { - ContextBase::mGps_conf.SUPL_ES = newSuplEs; - } - err = LOCATION_ERROR_SUCCESS; - if (index < mCount) { - errs[index] = err; - } - index++; - } - if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) { - uint32_t newSuplMode = mAdapter.convertSuplMode(mConfig.suplModeMask); - if (newSuplMode != ContextBase::mGps_conf.SUPL_MODE) { - ContextBase::mGps_conf.SUPL_MODE = newSuplMode; - mAdapter.getUlpProxy()->setCapabilities( - ContextBase::getCarrierCapabilities()); - mAdapter.broadcastCapabilities(mAdapter.getCapabilities()); - } - err = LOCATION_ERROR_SUCCESS; - if (index < mCount) { - errs[index] = err; - } - index++; - } - - mAdapter.reportResponse(index, errs, mIds); - delete[] errs; - } - }; - - if (NULL != ids) { - sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count)); - } else { - LOC_LOGE("%s]: No GNSS config items to update", __func__); - } - - return ids; -} - -uint32_t -GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data) -{ - uint32_t sessionId = generateSessionId(); - LOC_LOGD("%s]: id %u", __func__, sessionId); - - struct MsgDeleteAidingData : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - uint32_t mSessionId; - GnssAidingData mData; - inline MsgDeleteAidingData(GnssAdapter& adapter, - LocApiBase& api, - uint32_t sessionId, - GnssAidingData& data) : - LocMsg(), - mAdapter(adapter), - mApi(api), - mSessionId(sessionId), - mData(data) {} - inline virtual void proc() const { - LocationError err = LOCATION_ERROR_SUCCESS; - err = mApi.deleteAidingData(mData); - mAdapter.reportResponse(err, mSessionId); - SystemStatus* s = mAdapter.getSystemStatus(); - if ((nullptr != s) && (mData.deleteAll)) { - s->setDefaultGnssEngineStates(); - } - } - }; - - sendMsg(new MsgDeleteAidingData(*this, *mLocApi, sessionId, data)); - return sessionId; -} - -void -GnssAdapter::gnssUpdateXtraThrottleCommand(const bool enabled) -{ - LOC_LOGD("%s] enabled:%d", __func__, enabled); - - struct UpdateXtraThrottleMsg : public LocMsg { - GnssAdapter& mAdapter; - const bool mEnabled; - inline UpdateXtraThrottleMsg(GnssAdapter& adapter, const bool enabled) : - LocMsg(), - mAdapter(adapter), - mEnabled(enabled) {} - inline virtual void proc() const { - mAdapter.mXtraObserver.updateXtraThrottle(mEnabled); - } - }; - - sendMsg(new UpdateXtraThrottleMsg(*this, enabled)); -} - -void -GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy) -{ - LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f", - __func__, latitude, longitude, accuracy); - - struct MsgInjectLocation : public LocMsg { - LocApiBase& mApi; - ContextBase& mContext; - double mLatitude; - double mLongitude; - float mAccuracy; - inline MsgInjectLocation(LocApiBase& api, - ContextBase& context, - double latitude, - double longitude, - float accuracy) : - LocMsg(), - mApi(api), - mContext(context), - mLatitude(latitude), - mLongitude(longitude), - mAccuracy(accuracy) {} - inline virtual void proc() const { - if (!mContext.hasCPIExtendedCapabilities()) { - mApi.injectPosition(mLatitude, mLongitude, mAccuracy); - } - } - }; - - sendMsg(new MsgInjectLocation(*mLocApi, *mContext, latitude, longitude, accuracy)); -} - -void -GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty) -{ - LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d", - __func__, (long long)time, (long long)timeReference, uncertainty); - - struct MsgInjectTime : public LocMsg { - LocApiBase& mApi; - ContextBase& mContext; - int64_t mTime; - int64_t mTimeReference; - int32_t mUncertainty; - inline MsgInjectTime(LocApiBase& api, - ContextBase& context, - int64_t time, - int64_t timeReference, - int32_t uncertainty) : - LocMsg(), - mApi(api), - mContext(context), - mTime(time), - mTimeReference(timeReference), - mUncertainty(uncertainty) {} - inline virtual void proc() const { - mApi.setTime(mTime, mTimeReference, mUncertainty); - } - }; - - sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty)); -} - -void -GnssAdapter::setUlpProxyCommand(UlpProxyBase* ulp) -{ - LOC_LOGD("%s]: ", __func__); - - struct MsgSetUlpProxy : public LocMsg { - GnssAdapter& mAdapter; - UlpProxyBase* mUlp; - inline MsgSetUlpProxy(GnssAdapter& adapter, - UlpProxyBase* ulp) : - LocMsg(), - mAdapter(adapter), - mUlp(ulp) {} - inline virtual void proc() const { - mAdapter.setUlpProxy(mUlp); - if (mUlp) { - mUlp->setCapabilities(ContextBase::getCarrierCapabilities()); - } - } - }; - - sendMsg(new MsgSetUlpProxy(*this, ulp)); -} - -void -GnssAdapter::setUlpProxy(UlpProxyBase* ulp) -{ - if (ulp == mUlpProxy) { - //This takes care of the case when double initalization happens - //and we get the same object back for UlpProxyBase . Do nothing - return; - } - - LOC_LOGV("%s]: %p", __func__, ulp); - if (NULL == ulp) { - LOC_LOGE("%s]: ulp pointer is NULL", __func__); - ulp = new UlpProxyBase(); - } - - if (LOC_POSITION_MODE_INVALID != mUlpProxy->mPosMode.mode) { - // need to send this mode and start msg to ULP - ulp->sendFixMode(mUlpProxy->mPosMode); - } - - if (mUlpProxy->mFixSet) { - ulp->sendStartFix(); - } - - delete mUlpProxy; - mUlpProxy = ulp; -} - -void -GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks) -{ - LOC_LOGD("%s]: client %p", __func__, client); - - struct MsgAddClient : public LocMsg { - GnssAdapter& mAdapter; - LocationAPI* mClient; - const LocationCallbacks mCallbacks; - inline MsgAddClient(GnssAdapter& adapter, - LocationAPI* client, - const LocationCallbacks& callbacks) : - LocMsg(), - mAdapter(adapter), - mClient(client), - mCallbacks(callbacks) {} - inline virtual void proc() const { - mAdapter.saveClient(mClient, mCallbacks); - } - }; - - sendMsg(new MsgAddClient(*this, client, callbacks)); -} - -void -GnssAdapter::removeClientCommand(LocationAPI* client) -{ - LOC_LOGD("%s]: client %p", __func__, client); - - struct MsgRemoveClient : public LocMsg { - GnssAdapter& mAdapter; - LocationAPI* mClient; - inline MsgRemoveClient(GnssAdapter& adapter, - LocationAPI* client) : - LocMsg(), - mAdapter(adapter), - mClient(client) {} - inline virtual void proc() const { - mAdapter.stopClientSessions(mClient); - mAdapter.eraseClient(mClient); - } - }; - - sendMsg(new MsgRemoveClient(*this, client)); -} - -void -GnssAdapter::stopClientSessions(LocationAPI* client) -{ - LOC_LOGD("%s]: client %p", __func__, client); - for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end();) { - if (client == it->first.client) { - LocationError err = stopTrackingMultiplex(it->first.client, it->first.id); - if (LOCATION_ERROR_SUCCESS == err) { - it = mTrackingSessions.erase(it); - continue; - } - } - ++it; // increment only when not erasing an iterator - } - -} - -void -GnssAdapter::updateClientsEventMask() -{ - LOC_API_ADAPTER_EVENT_MASK_T mask = 0; - for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { - if (it->second.trackingCb != nullptr) { - mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT; - } - if (it->second.gnssNiCb != nullptr) { - mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST; - } - if (it->second.gnssSvCb != nullptr) { - mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT; - } - if ((it->second.gnssNmeaCb != nullptr) && (mNmeaMask)) { - mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT; - } - if (it->second.gnssMeasurementsCb != nullptr) { - mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT; - } - } - - /* - ** For Automotive use cases we need to enable MEASUREMENT and POLY - ** when QDR is enabled - */ - if(1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) { - mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT; - mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT; - - LOC_LOGD("%s]: Auto usecase, Enable MEAS/POLY - mask 0x%" PRIu64 "", __func__, mask); - } - - if (mAgpsCbInfo.statusV4Cb != NULL) { - mask |= LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST; - } - - // Add ODCPI handling - if (nullptr != mOdcpiRequestCb) { - mask |= LOC_API_ADAPTER_BIT_REQUEST_WIFI; - } - - updateEvtMask(mask, LOC_REGISTRATION_MASK_SET); -} - -void -GnssAdapter::handleEngineUpEvent() -{ - struct MsgRestartSessions : public LocMsg { - GnssAdapter& mAdapter; - inline MsgRestartSessions(GnssAdapter& adapter) : - LocMsg(), - mAdapter(adapter) {} - virtual void proc() const { - mAdapter.restartSessions(); - } - }; - - setConfigCommand(); - sendMsg(new MsgRestartSessions(*this)); -} - -void -GnssAdapter::restartSessions() -{ - LOC_LOGD("%s]: ", __func__); - - // odcpi session is no longer active after restart - mOdcpiRequestActive = false; - - if (mTrackingSessions.empty()) { - return; - } - - // get the LocationOptions that has the smallest interval, which should be the active one - LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time - for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) { - if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet - it->second.minInterval < smallestIntervalOptions.minInterval) { - smallestIntervalOptions = it->second; - } - } - - LocPosMode locPosMode = {}; - convertOptions(locPosMode, smallestIntervalOptions); - mLocApi->startFix(locPosMode); -} - -void -GnssAdapter::requestCapabilitiesCommand(LocationAPI* client) -{ - LOC_LOGD("%s]: ", __func__); - - struct MsgRequestCapabilities : public LocMsg { - GnssAdapter& mAdapter; - LocationAPI* mClient; - inline MsgRequestCapabilities(GnssAdapter& adapter, - LocationAPI* client) : - LocMsg(), - mAdapter(adapter), - mClient(client) {} - inline virtual void proc() const { - LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient); - if (callbacks.capabilitiesCb == nullptr) { - LOC_LOGE("%s]: capabilitiesCb is NULL", __func__); - return; - } - - LocationCapabilitiesMask mask = mAdapter.getCapabilities(); - callbacks.capabilitiesCb(mask); - } - }; - - sendMsg(new MsgRequestCapabilities(*this, client)); -} - -LocationCapabilitiesMask -GnssAdapter::getCapabilities() -{ - LocationCapabilitiesMask mask = 0; - uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities(); - // time based tracking always supported - mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT; - // geofence always supported - mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT; - if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) { - mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT; - } - if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) { - mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT; - } - if (mLocApi == nullptr) - return mask; - if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)) { - mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT | - LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT; - } - if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) { - mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT; - } - if (mLocApi->isMessageSupported(LOC_API_ADAPTER_MESSAGE_OUTDOOR_TRIP_BATCHING)) { - mask |= LOCATION_CAPABILITIES_OUTDOOR_TRIP_BATCHING_BIT; - } - if (mLocApi->gnssConstellationConfig()) { - mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT; - } - if (mLocApi->isFeatureSupported(LOC_SUPPORTED_FEATURE_DEBUG_NMEA_V02)) { - mask |= LOCATION_CAPABILITIES_DEBUG_NMEA_BIT; - } - return mask; -} - -void -GnssAdapter::broadcastCapabilities(LocationCapabilitiesMask mask) -{ - for (auto it = mClientData.begin(); it != mClientData.end(); ++it) { - if (nullptr != it->second.capabilitiesCb) { - it->second.capabilitiesCb(mask); - } - } -} - -LocationCallbacks -GnssAdapter::getClientCallbacks(LocationAPI* client) -{ - LocationCallbacks callbacks = {}; - auto it = mClientData.find(client); - if (it != mClientData.end()) { - callbacks = it->second; - } - return callbacks; -} - -void -GnssAdapter::saveClient(LocationAPI* client, const LocationCallbacks& callbacks) -{ - mClientData[client] = callbacks; - updateClientsEventMask(); -} - -void -GnssAdapter::eraseClient(LocationAPI* client) -{ - auto it = mClientData.find(client); - if (it != mClientData.end()) { - mClientData.erase(it); - } - updateClientsEventMask(); -} - -bool -GnssAdapter::hasTrackingCallback(LocationAPI* client) -{ - auto it = mClientData.find(client); - return (it != mClientData.end() && it->second.trackingCb); -} - -bool -GnssAdapter::hasMeasurementsCallback(LocationAPI* client) -{ - auto it = mClientData.find(client); - return (it != mClientData.end() && it->second.gnssMeasurementsCb); -} - -bool -GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId) -{ - LocationSessionKey key(client, sessionId); - return (mTrackingSessions.find(key) != mTrackingSessions.end()); -} - -void -GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId, - const LocationOptions& options) -{ - LocationSessionKey key(client, sessionId); - mTrackingSessions[key] = options; -} - -void -GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId) -{ - LocationSessionKey key(client, sessionId); - auto it = mTrackingSessions.find(key); - if (it != mTrackingSessions.end()) { - mTrackingSessions.erase(it); - } - -} - -bool GnssAdapter::setUlpPositionMode(const LocPosMode& mode) { - if (!mUlpPositionMode.equals(mode)) { - mUlpPositionMode = mode; - return true; - } else { - return false; - } -} - -void -GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId) -{ - LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err); - - auto it = mClientData.find(client); - if (it != mClientData.end() && - it->second.responseCb != nullptr) { - it->second.responseCb(err, sessionId); - } else { - LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId); - } -} - -void -GnssAdapter::reportResponse(LocationError err, uint32_t sessionId) -{ - LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err); - - if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) { - mControlCallbacks.responseCb(err, sessionId); - } else { - LOC_LOGW("%s]: control client response callback not found", __func__); - } -} - -void -GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids) -{ - IF_LOC_LOGD { - std::string idsString = "["; - std::string errsString = "["; - if (NULL != ids && NULL != errs) { - for (size_t i=0; i < count; ++i) { - idsString += std::to_string(ids[i]) + " "; - errsString += std::to_string(errs[i]) + " "; - } - } - idsString += "]"; - errsString += "]"; - - LOC_LOGD("%s]: ids %s errs %s", - __func__, idsString.c_str(), errsString.c_str()); - } - - if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) { - mControlCallbacks.collectiveResponseCb(count, errs, ids); - } else { - LOC_LOGW("%s]: control client callback not found", __func__); - } -} - -uint32_t -GnssAdapter::startTrackingCommand(LocationAPI* client, LocationOptions& options) -{ - uint32_t sessionId = generateSessionId(); - LOC_LOGD("%s]: client %p id %u minInterval %u mode %u", - __func__, client, sessionId, options.minInterval, options.mode); - - struct MsgStartTracking : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - LocationAPI* mClient; - uint32_t mSessionId; - LocationOptions mOptions; - inline MsgStartTracking(GnssAdapter& adapter, - LocApiBase& api, - LocationAPI* client, - uint32_t sessionId, - LocationOptions options) : - LocMsg(), - mAdapter(adapter), - mApi(api), - mClient(client), - mSessionId(sessionId), - mOptions(options) {} - inline virtual void proc() const { - LocationError err = LOCATION_ERROR_SUCCESS; - if (!mAdapter.hasTrackingCallback(mClient) && - !mAdapter.hasMeasurementsCallback(mClient)) { - err = LOCATION_ERROR_CALLBACK_MISSING; - } else if (0 == mOptions.size) { - err = LOCATION_ERROR_INVALID_PARAMETER; - } else { - // Api doesn't support multiple clients for time based tracking, so mutiplex - err = mAdapter.startTrackingMultiplex(mOptions); - if (LOCATION_ERROR_SUCCESS == err) { - mAdapter.saveTrackingSession(mClient, mSessionId, mOptions); - } - } - mAdapter.reportResponse(mClient, err, mSessionId); - } - }; - - sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options)); - return sessionId; - -} - -LocationError -GnssAdapter::startTrackingMultiplex(const LocationOptions& options) -{ - LocationError err = LOCATION_ERROR_SUCCESS; - - if (mTrackingSessions.empty()) { - err = startTracking(options); - } else { - // get the LocationOptions that has the smallest interval, which should be the active one - LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time - for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) { - if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet - it->second.minInterval < smallestIntervalOptions.minInterval) { - smallestIntervalOptions = it->second; - } - } - // if new session's minInterval is smaller than any in other sessions - if (options.minInterval < smallestIntervalOptions.minInterval) { - // restart time based tracking with new options - err = startTracking(options); - } - } - - return err; -} - -LocationError -GnssAdapter::startTracking(const LocationOptions& options) -{ - LocationError err = LOCATION_ERROR_SUCCESS; - LocPosMode locPosMode = {}; - convertOptions(locPosMode, options); - if (!mUlpProxy->sendFixMode(locPosMode)) { - // do nothing - } - if (!mUlpProxy->sendStartFix()) { - loc_api_adapter_err apiErr = mLocApi->startFix(locPosMode); - if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) { - err = LOCATION_ERROR_SUCCESS; - } else { - err = LOCATION_ERROR_GENERAL_FAILURE; - } - } - - return err; -} - -void -GnssAdapter::setPositionModeCommand(LocPosMode& locPosMode) -{ - LOC_LOGD("%s]: min_interval %u mode %u", - __func__, locPosMode.min_interval, locPosMode.mode); - - struct MsgSetPositionMode : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - LocPosMode mLocPosMode; - inline MsgSetPositionMode(GnssAdapter& adapter, - LocApiBase& api, - LocPosMode& locPosMode) : - LocMsg(), - mAdapter(adapter), - mApi(api), - mLocPosMode(locPosMode) {} - inline virtual void proc() const { - // saves the mode in adapter to be used when startTrackingCommand is called from ULP - if (mAdapter.setUlpPositionMode(mLocPosMode)) { - mApi.setPositionMode(mLocPosMode); - } - } - }; - - sendMsg(new MsgSetPositionMode(*this, *mLocApi, locPosMode)); -} - -void -GnssAdapter::startTrackingCommand() -{ - LOC_LOGD("%s]: ", __func__); - - struct MsgStartTracking : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - inline MsgStartTracking(GnssAdapter& adapter, - LocApiBase& api) : - LocMsg(), - mAdapter(adapter), - mApi(api) {} - inline virtual void proc() const { - // we get this call from ULP, so just call LocApi without multiplexing because - // ulp would be doing the multiplexing for us if it is present - if (!mAdapter.isInSession()) { - LocPosMode& ulpPositionMode = mAdapter.getUlpPositionMode(); - mApi.startFix(ulpPositionMode); - } - } - }; - - sendMsg(new MsgStartTracking(*this, *mLocApi)); -} - -void -GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id, - LocationOptions& options) -{ - LOC_LOGD("%s]: client %p id %u minInterval %u mode %u", - __func__, client, id, options.minInterval, options.mode); - - struct MsgUpdateTracking : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - LocationAPI* mClient; - uint32_t mSessionId; - LocationOptions mOptions; - inline MsgUpdateTracking(GnssAdapter& adapter, - LocApiBase& api, - LocationAPI* client, - uint32_t sessionId, - LocationOptions options) : - LocMsg(), - mAdapter(adapter), - mApi(api), - mClient(client), - mSessionId(sessionId), - mOptions(options) {} - inline virtual void proc() const { - if (mAdapter.isTrackingSession(mClient, mSessionId)) { - LocationError err = LOCATION_ERROR_SUCCESS; - if (0 == mOptions.size) { - err = LOCATION_ERROR_INVALID_PARAMETER; - } else { - // Api doesn't support multiple clients for time based tracking, so mutiplex - err = mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions); - if (LOCATION_ERROR_SUCCESS == err) { - mAdapter.saveTrackingSession(mClient, mSessionId, mOptions); - } - } - mAdapter.reportResponse(mClient, err, mSessionId); - } - // we do not reportResponse for the case where there is no existing tracking session - // for the client and id being used, since updateTrackingCommand can be sent to both - // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response - } - }; - - sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options)); -} - -LocationError -GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id, - const LocationOptions& options) -{ - LocationError err = LOCATION_ERROR_SUCCESS; - - if (1 == mTrackingSessions.size()) { - err = startTracking(options); - } else { - LocationSessionKey key(client, id); - - // get the session we are updating - auto it = mTrackingSessions.find(key); - if (it != mTrackingSessions.end()) { - // find the smallest interval, other than the session we are updating - LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time - for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) { - // if session is not the one we are updating and either smallest interval is not set - // or there is a new smallest interval, then set the new smallest interval - if (it2->first != key && (0 == smallestIntervalOptions.size || - it2->second.minInterval < smallestIntervalOptions.minInterval)) { - smallestIntervalOptions = it2->second; - } - } - // if session we are updating has smaller interval then next smallest - if (options.minInterval < smallestIntervalOptions.minInterval) { - // restart time based tracking with the newly updated interval - err = startTracking(options); - // else if the session we are updating used to be the smallest - } else if (it->second.minInterval < smallestIntervalOptions.minInterval) { - // restart time based tracking with the next smallest - err = startTracking(smallestIntervalOptions); - } - } - } - - return err; -} - -void -GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id) -{ - LOC_LOGD("%s]: client %p id %u", __func__, client, id); - - struct MsgStopTracking : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - LocationAPI* mClient; - uint32_t mSessionId; - inline MsgStopTracking(GnssAdapter& adapter, - LocApiBase& api, - LocationAPI* client, - uint32_t sessionId) : - LocMsg(), - mAdapter(adapter), - mApi(api), - mClient(client), - mSessionId(sessionId) {} - inline virtual void proc() const { - if (mAdapter.isTrackingSession(mClient, mSessionId)) { - LocationError err = LOCATION_ERROR_SUCCESS; - // Api doesn't support multiple clients for time based tracking, so mutiplex - err = mAdapter.stopTrackingMultiplex(mClient, mSessionId); - if (LOCATION_ERROR_SUCCESS == err) { - mAdapter.eraseTrackingSession(mClient, mSessionId); - } - mAdapter.reportResponse(mClient, err, mSessionId); - } - // we do not reportResponse for the case where there is no existing tracking session - // for the client and id being used, since stopTrackingCommand can be sent to both - // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response - - } - }; - - sendMsg(new MsgStopTracking(*this, *mLocApi, client, id)); -} - -LocationError -GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id) -{ - LocationError err = LOCATION_ERROR_SUCCESS; - - if (1 == mTrackingSessions.size()) { - err = stopTracking(); - } else { - LocationSessionKey key(client, id); - - // get the session we are stopping - auto it = mTrackingSessions.find(key); - if (it != mTrackingSessions.end()) { - // find the next smallest interval, other than the session we are stopping - LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time - for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) { - // if session is not the one we are stopping and either smallest interval is not set - // or there is a new smallest interval, then set the new smallest interval - if (it2->first != key && (0 == smallestIntervalOptions.size || - it2->second.minInterval < smallestIntervalOptions.minInterval)) { - smallestIntervalOptions = it2->second; - } - } - // if session we are stopping has smaller interval then next smallest - if (it->second.minInterval < smallestIntervalOptions.minInterval) { - // restart time based tracking with next smallest interval - err = startTracking(smallestIntervalOptions); - } - } - } - - return err; -} - -LocationError -GnssAdapter::stopTracking() -{ - LocationError err = LOCATION_ERROR_SUCCESS; - if (!mUlpProxy->sendStopFix()) { - loc_api_adapter_err apiErr = mLocApi->stopFix(); - if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) { - err = LOCATION_ERROR_SUCCESS; - } else { - err = LOCATION_ERROR_GENERAL_FAILURE; - } - } - - return err; -} - -void -GnssAdapter::stopTrackingCommand() -{ - LOC_LOGD("%s]: ", __func__); - - struct MsgStopTracking : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - inline MsgStopTracking(GnssAdapter& adapter, - LocApiBase& api) : - LocMsg(), - mAdapter(adapter), - mApi(api) {} - inline virtual void proc() const { - // clear the position mode - LocPosMode mLocPosMode = {}; - mLocPosMode.mode = LOC_POSITION_MODE_INVALID; - mAdapter.setUlpPositionMode(mLocPosMode); - // don't need to multiplex because ULP will do that for us if it is present - mApi.stopFix(); - } - }; - - sendMsg(new MsgStopTracking(*this, *mLocApi)); -} - -void -GnssAdapter::getZppCommand() -{ - LOC_LOGD("%s]: ", __func__); - - struct MsgGetZpp : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - inline MsgGetZpp(GnssAdapter& adapter, - LocApiBase& api) : - LocMsg(), - mAdapter(adapter), - mApi(api) {} - inline virtual void proc() const { - UlpLocation location = {}; - LocPosTechMask techMask = LOC_POS_TECH_MASK_DEFAULT; - GpsLocationExtended locationExtended = {}; - locationExtended.size = sizeof(locationExtended); - - mApi.getBestAvailableZppFix(location.gpsLocation, locationExtended, - techMask); - //Mark the location source as from ZPP - location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO; - location.position_source = ULP_LOCATION_IS_FROM_ZPP; - - mAdapter.getUlpProxy()->reportPosition(location, - locationExtended, - LOC_SESS_SUCCESS, - techMask); - } - }; - - sendMsg(new MsgGetZpp(*this, *mLocApi)); -} - -bool -GnssAdapter::hasNiNotifyCallback(LocationAPI* client) -{ - auto it = mClientData.find(client); - return (it != mClientData.end() && it->second.gnssNiCb); -} - -void -GnssAdapter::gnssNiResponseCommand(LocationAPI* client, - uint32_t id, - GnssNiResponse response) -{ - LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response); - - struct MsgGnssNiResponse : public LocMsg { - GnssAdapter& mAdapter; - LocationAPI* mClient; - uint32_t mSessionId; - GnssNiResponse mResponse; - inline MsgGnssNiResponse(GnssAdapter& adapter, - LocationAPI* client, - uint32_t sessionId, - GnssNiResponse response) : - LocMsg(), - mAdapter(adapter), - mClient(client), - mSessionId(sessionId), - mResponse(response) {} - inline virtual void proc() const { - NiData& niData = mAdapter.getNiData(); - LocationError err = LOCATION_ERROR_SUCCESS; - if (!mAdapter.hasNiNotifyCallback(mClient)) { - err = LOCATION_ERROR_ID_UNKNOWN; - } else { - NiSession* pSession = NULL; - if (mSessionId == niData.sessionEs.reqID && - NULL != niData.sessionEs.rawRequest) { - pSession = &niData.sessionEs; - // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted - if (mResponse == GNSS_NI_RESPONSE_ACCEPT && - NULL != niData.session.rawRequest) { - pthread_mutex_lock(&niData.session.tLock); - niData.session.resp = GNSS_NI_RESPONSE_IGNORE; - niData.session.respRecvd = true; - pthread_cond_signal(&niData.session.tCond); - pthread_mutex_unlock(&niData.session.tLock); - } - } else if (mSessionId == niData.session.reqID && - NULL != niData.session.rawRequest) { - pSession = &niData.session; - } - - if (pSession) { - LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u", - __func__, mResponse, mSessionId); - pthread_mutex_lock(&pSession->tLock); - pSession->resp = mResponse; - pSession->respRecvd = true; - pthread_cond_signal(&pSession->tCond); - pthread_mutex_unlock(&pSession->tLock); - } else { - err = LOCATION_ERROR_ID_UNKNOWN; - LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session", - __func__, mSessionId); - } - } - mAdapter.reportResponse(mClient, err, mSessionId); - } - }; - - sendMsg(new MsgGnssNiResponse(*this, client, id, response)); - -} - -void -GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest) -{ - LOC_LOGD("%s]: response %u", __func__, response); - - struct MsgGnssNiResponse : public LocMsg { - LocApiBase& mApi; - const GnssNiResponse mResponse; - const void* mPayload; - inline MsgGnssNiResponse(LocApiBase& api, - const GnssNiResponse response, - const void* rawRequest) : - LocMsg(), - mApi(api), - mResponse(response), - mPayload(rawRequest) {} - inline virtual ~MsgGnssNiResponse() { - // this is a bit weird since mPayload is not - // allocated by this class. But there is no better way. - // mPayload actually won't be NULL here. - free((void*)mPayload); - } - inline virtual void proc() const { - mApi.informNiResponse(mResponse, mPayload); - } - }; - - sendMsg(new MsgGnssNiResponse(*mLocApi, response, rawRequest)); - -} - -uint32_t -GnssAdapter::enableCommand(LocationTechnologyType techType) -{ - uint32_t sessionId = generateSessionId(); - LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType); - - struct MsgEnableGnss : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - ContextBase& mContext; - uint32_t mSessionId; - LocationTechnologyType mTechType; - inline MsgEnableGnss(GnssAdapter& adapter, - LocApiBase& api, - ContextBase& context, - uint32_t sessionId, - LocationTechnologyType techType) : - LocMsg(), - mAdapter(adapter), - mApi(api), - mContext(context), - mSessionId(sessionId), - mTechType(techType) {} - inline virtual void proc() const { - LocationError err = LOCATION_ERROR_SUCCESS; - uint32_t powerVoteId = mAdapter.getPowerVoteId(); - if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) { - err = LOCATION_ERROR_INVALID_PARAMETER; - } else if (powerVoteId > 0) { - err = LOCATION_ERROR_ALREADY_STARTED; - } else { - mAdapter.setPowerVoteId(mSessionId); - mApi.setGpsLock(GNSS_CONFIG_GPS_LOCK_NONE); - mAdapter.mXtraObserver.updateLockStatus( - mAdapter.convertGpsLock(GNSS_CONFIG_GPS_LOCK_NONE)); - } - mAdapter.reportResponse(err, mSessionId); - } - }; - - if (mContext != NULL) { - sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType)); - mContext->modemPowerVote(true); - } else { - LOC_LOGE("%s]: Context is NULL", __func__); - } - - return sessionId; -} - -void -GnssAdapter::disableCommand(uint32_t id) -{ - LOC_LOGD("%s]: id %u", __func__, id); - - struct MsgDisableGnss : public LocMsg { - GnssAdapter& mAdapter; - LocApiBase& mApi; - ContextBase& mContext; - uint32_t mSessionId; - inline MsgDisableGnss(GnssAdapter& adapter, - LocApiBase& api, - ContextBase& context, - uint32_t sessionId) : - LocMsg(), - mAdapter(adapter), - mApi(api), - mContext(context), - mSessionId(sessionId) {} - inline virtual void proc() const { - LocationError err = LOCATION_ERROR_SUCCESS; - uint32_t powerVoteId = mAdapter.getPowerVoteId(); - if (powerVoteId != mSessionId) { - err = LOCATION_ERROR_ID_UNKNOWN; - } else { - mAdapter.setPowerVoteId(0); - mApi.setGpsLock(mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK)); - mAdapter.mXtraObserver.updateLockStatus( - mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK)); - } - mAdapter.reportResponse(err, mSessionId); - } - }; - - if (mContext != NULL) { - sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id)); - mContext->modemPowerVote(false); - } - -} - -void -GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation, - const GpsLocationExtended& locationExtended, - enum loc_sess_status status, - LocPosTechMask techMask, - bool fromUlp) -{ - LOC_LOGD("%s]: fromUlp %u status %u", __func__, fromUlp, status); - - // if this event is not called from ULP, then try to call into ULP and return if successfull - if (!fromUlp) { - if (mUlpProxy->reportPosition(ulpLocation, locationExtended, - status, techMask)) { - return; - } - } - - struct MsgReportPosition : public LocMsg { - GnssAdapter& mAdapter; - const UlpLocation mUlpLocation; - const GpsLocationExtended mLocationExtended; - loc_sess_status mStatus; - LocPosTechMask mTechMask; - inline MsgReportPosition(GnssAdapter& adapter, - const UlpLocation& ulpLocation, - const GpsLocationExtended& locationExtended, - loc_sess_status status, - LocPosTechMask techMask) : - LocMsg(), - mAdapter(adapter), - mUlpLocation(ulpLocation), - mLocationExtended(locationExtended), - mStatus(status), - mTechMask(techMask) {} - inline virtual void proc() const { - // extract bug report info - this returns true if consumed by systemstatus - SystemStatus* s = mAdapter.getSystemStatus(); - if ((nullptr != s) && - ((LOC_SESS_SUCCESS == mStatus) || (LOC_SESS_INTERMEDIATE == mStatus))){ - s->eventPosition(mUlpLocation, mLocationExtended); - } - mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask); - } - }; - - sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended, status, techMask)); -} - -bool -GnssAdapter::needReport(const UlpLocation& ulpLocation, - enum loc_sess_status status, - LocPosTechMask techMask) { - bool reported = false; - if (LOC_SESS_SUCCESS == status) { - // this is a final fix - LocPosTechMask mask = - LOC_POS_TECH_MASK_SATELLITE | LOC_POS_TECH_MASK_SENSORS | LOC_POS_TECH_MASK_HYBRID; - // it is a Satellite fix or a sensor fix - reported = (mask & techMask); - } else if (LOC_SESS_INTERMEDIATE == status && - LOC_SESS_INTERMEDIATE == ContextBase::mGps_conf.INTERMEDIATE_POS) { - // this is a intermediate fix and we accepte intermediate - - // it is NOT the case that - // there is inaccuracy; and - // we care about inaccuracy; and - // the inaccuracy exceeds our tolerance - reported = !((ulpLocation.gpsLocation.flags & LOC_GPS_LOCATION_HAS_ACCURACY) && - (ContextBase::mGps_conf.ACCURACY_THRES != 0) && - (ulpLocation.gpsLocation.accuracy > ContextBase::mGps_conf.ACCURACY_THRES)); - } - - return reported; -} - -void -GnssAdapter::reportPosition(const UlpLocation& ulpLocation, - const GpsLocationExtended& locationExtended, - enum loc_sess_status status, - LocPosTechMask techMask) -{ - bool reported = needReport(ulpLocation, status, techMask); - if (reported) { - if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) { - mGnssSvIdUsedInPosAvail = true; - mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids; - } - for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { - if (nullptr != it->second.trackingCb) { - Location location = {}; - convertLocation(location, ulpLocation.gpsLocation, locationExtended, techMask); - it->second.trackingCb(location); - } - if (nullptr != it->second.gnssLocationInfoCb) { - GnssLocationInfoNotification locationInfo = {}; - convertLocationInfo(locationInfo, locationExtended); - it->second.gnssLocationInfoCb(locationInfo); - } - } - } - - if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) { - /*Only BlankNMEA sentence needs to be processed and sent, if both lat, long is 0 & - horReliability is not set. */ - bool blank_fix = ((0 == ulpLocation.gpsLocation.latitude) && - (0 == ulpLocation.gpsLocation.longitude) && - (LOC_RELIABILITY_NOT_SET == locationExtended.horizontal_reliability)); - uint8_t generate_nmea = (reported && status != LOC_SESS_FAILURE && !blank_fix); - std::vector<std::string> nmeaArraystr; - loc_nmea_generate_pos(ulpLocation, locationExtended, generate_nmea, nmeaArraystr); - for (auto sentence : nmeaArraystr) { - reportNmea(sentence.c_str(), sentence.length()); - } - } - - // Free the allocated memory for rawData - UlpLocation* gp = (UlpLocation*)&(ulpLocation); - if (gp != NULL && gp->rawData != NULL) - { - delete (char*)gp->rawData; - gp->rawData = NULL; - gp->rawDataSize = 0; - } -} - -void -GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify, - bool fromUlp) -{ - LOC_LOGD("%s]: fromUlp %u", __func__, fromUlp); - - // if this event is not called from ULP, then try to call into ULP and return if successfull - if (!fromUlp) { - if (mUlpProxy->reportSv(svNotify)) { - return; - } - } - - struct MsgReportSv : public LocMsg { - GnssAdapter& mAdapter; - const GnssSvNotification mSvNotify; - inline MsgReportSv(GnssAdapter& adapter, - const GnssSvNotification& svNotify) : - LocMsg(), - mAdapter(adapter), - mSvNotify(svNotify) {} - inline virtual void proc() const { - mAdapter.reportSv((GnssSvNotification&)mSvNotify); - } - }; - - sendMsg(new MsgReportSv(*this, svNotify)); -} - -void -GnssAdapter::reportSv(GnssSvNotification& svNotify) -{ - int numSv = svNotify.count; - int16_t gnssSvId = 0; - uint64_t svUsedIdMask = 0; - for (int i=0; i < numSv; i++) { - svUsedIdMask = 0; - gnssSvId = svNotify.gnssSvs[i].svId; - switch (svNotify.gnssSvs[i].type) { - case GNSS_SV_TYPE_GPS: - if (mGnssSvIdUsedInPosAvail) { - svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask; - } - break; - case GNSS_SV_TYPE_GLONASS: - if (mGnssSvIdUsedInPosAvail) { - svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask; - } - break; - case GNSS_SV_TYPE_BEIDOU: - if (mGnssSvIdUsedInPosAvail) { - svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask; - } - break; - case GNSS_SV_TYPE_GALILEO: - if (mGnssSvIdUsedInPosAvail) { - svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask; - } - break; - case GNSS_SV_TYPE_QZSS: - if (mGnssSvIdUsedInPosAvail) { - svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask; - } - // QZSS SV id's need to reported as it is to framework, since - // framework expects it as it is. See GnssStatus.java. - // SV id passed to here by LocApi is 1-based. - svNotify.gnssSvs[i].svId += (QZSS_SV_PRN_MIN - 1); - break; - default: - svUsedIdMask = 0; - break; - } - - // If SV ID was used in previous position fix, then set USED_IN_FIX - // flag, else clear the USED_IN_FIX flag. - if (svUsedIdMask & (1 << (gnssSvId - 1))) { - svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT; - } - } - - for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { - if (nullptr != it->second.gnssSvCb) { - it->second.gnssSvCb(svNotify); - } - } - - if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) { - std::vector<std::string> nmeaArraystr; - loc_nmea_generate_sv(svNotify, nmeaArraystr); - for (auto sentence : nmeaArraystr) { - reportNmea(sentence.c_str(), sentence.length()); - } - } - - mGnssSvIdUsedInPosAvail = false; -} - -void -GnssAdapter::reportNmeaEvent(const char* nmea, size_t length, bool fromUlp) -{ - // if this event is not called from ULP, then try to call into ULP and return if successfull - if (!fromUlp && !loc_nmea_is_debug(nmea, length)) { - if (mUlpProxy->reportNmea(nmea, length)) { - return; - } - } - - struct MsgReportNmea : public LocMsg { - GnssAdapter& mAdapter; - const char* mNmea; - size_t mLength; - inline MsgReportNmea(GnssAdapter& adapter, - const char* nmea, - size_t length) : - LocMsg(), - mAdapter(adapter), - mNmea(new char[length+1]), - mLength(length) { - if (mNmea == nullptr) { - LOC_LOGE("%s] new allocation failed, fatal error.", __func__); - return; - } - strlcpy((char*)mNmea, nmea, length+1); - } - inline virtual ~MsgReportNmea() - { - delete[] mNmea; - } - inline virtual void proc() const { - // extract bug report info - this returns true if consumed by systemstatus - bool ret = false; - SystemStatus* s = mAdapter.getSystemStatus(); - if (nullptr != s) { - ret = s->setNmeaString(mNmea, mLength); - } - if (false == ret) { - // forward NMEA message to upper layer - mAdapter.reportNmea(mNmea, mLength); - } - } - }; - - sendMsg(new MsgReportNmea(*this, nmea, length)); -} - -void -GnssAdapter::reportNmea(const char* nmea, size_t length) -{ - GnssNmeaNotification nmeaNotification = {}; - nmeaNotification.size = sizeof(GnssNmeaNotification); - - struct timeval tv; - gettimeofday(&tv, (struct timezone *) NULL); - int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000; - nmeaNotification.timestamp = now; - nmeaNotification.nmea = nmea; - nmeaNotification.length = length; - - for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { - if (nullptr != it->second.gnssNmeaCb) { - it->second.gnssNmeaCb(nmeaNotification); - } - } -} - -bool -GnssAdapter::requestNiNotifyEvent(const GnssNiNotification ¬ify, const void* data) -{ - LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d" - "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s", - __func__, notify.type, notify.timeout, notify.timeoutResponse, - notify.requestor, notify.requestorEncoding, - notify.message, notify.messageEncoding, notify.extras); - - struct MsgReportNiNotify : public LocMsg { - GnssAdapter& mAdapter; - const GnssNiNotification mNotify; - const void* mData; - inline MsgReportNiNotify(GnssAdapter& adapter, - const GnssNiNotification& notify, - const void* data) : - LocMsg(), - mAdapter(adapter), - mNotify(notify), - mData(data) {} - inline virtual void proc() const { - mAdapter.requestNiNotify(mNotify, mData); - } - }; - - sendMsg(new MsgReportNiNotify(*this, notify, data)); - - return true; -} - -static void* niThreadProc(void *args) -{ - NiSession* pSession = (NiSession*)args; - int rc = 0; /* return code from pthread calls */ - - struct timespec present_time; - struct timespec expire_time; - - pthread_mutex_lock(&pSession->tLock); - /* Calculate absolute expire time */ - clock_gettime(CLOCK_MONOTONIC, &present_time); - expire_time.tv_sec = present_time.tv_sec + pSession->respTimeLeft; - expire_time.tv_nsec = present_time.tv_nsec; - LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec", - __func__, (long)expire_time.tv_sec, pSession->respTimeLeft); - - while (!pSession->respRecvd) { - rc = pthread_cond_timedwait(&pSession->tCond, - &pSession->tLock, - &expire_time); - if (rc == ETIMEDOUT) { - pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE; - LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d", - __func__, rc); - break; - } - } - LOC_LOGD("%s]: Java layer has sent us a user response and return value from " - "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp); - pSession->respRecvd = false; /* Reset the user response flag for the next session*/ - - // adding this check to support modem restart, in which case, we need the thread - // to exit without calling sending data. We made sure that rawRequest is NULL in - // loc_eng_ni_reset_on_engine_restart() - GnssAdapter* adapter = pSession->adapter; - GnssNiResponse resp; - void* rawRequest = NULL; - bool sendResponse = false; - - if (NULL != pSession->rawRequest) { - if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) { - resp = pSession->resp; - rawRequest = pSession->rawRequest; - sendResponse = true; - } else { - free(pSession->rawRequest); - } - pSession->rawRequest = NULL; - } - pthread_mutex_unlock(&pSession->tLock); - - pSession->respTimeLeft = 0; - pSession->reqID = 0; - - if (sendResponse) { - adapter->gnssNiResponseCommand(resp, rawRequest); - } - - return NULL; -} - -bool -GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data) -{ - NiSession* pSession = NULL; - gnssNiCallback gnssNiCb = nullptr; - - for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { - if (nullptr != it->second.gnssNiCb) { - gnssNiCb = it->second.gnssNiCb; - break; - } - } - if (nullptr == gnssNiCb) { - EXIT_LOG(%s, "no clients with gnssNiCb."); - return false; - } - - if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) { - if (NULL != mNiData.sessionEs.rawRequest) { - LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d", - __func__, notify.type); - if (NULL != data) { - free((void*)data); - } - } else { - pSession = &mNiData.sessionEs; - } - } else { - if (NULL != mNiData.session.rawRequest || - NULL != mNiData.sessionEs.rawRequest) { - LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d", - __func__, notify.type); - if (NULL != data) { - free((void*)data); - } - } else { - pSession = &mNiData.session; - } - } - - if (pSession) { - /* Save request */ - pSession->rawRequest = (void*)data; - pSession->reqID = ++mNiData.reqIDCounter; - pSession->adapter = this; - - int sessionId = pSession->reqID; - - /* For robustness, spawn a thread at this point to timeout to clear up the notification - * status, even though the OEM layer in java does not do so. - **/ - pSession->respTimeLeft = - 5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME); - - int rc = 0; - rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession); - if (rc) { - LOC_LOGE("%s]: Loc NI thread is not created.", __func__); - } - rc = pthread_detach(pSession->thread); - if (rc) { - LOC_LOGE("%s]: Loc NI thread is not detached.", __func__); - } - - if (nullptr != gnssNiCb) { - gnssNiCb(sessionId, notify); - } - } - - return true; -} - -void -GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurements, - int msInWeek) -{ - LOC_LOGD("%s]: msInWeek=%d", __func__, msInWeek); - - struct MsgReportGnssMeasurementData : public LocMsg { - GnssAdapter& mAdapter; - GnssMeasurementsNotification mMeasurementsNotify; - inline MsgReportGnssMeasurementData(GnssAdapter& adapter, - const GnssMeasurementsNotification& measurements, - int msInWeek) : - LocMsg(), - mAdapter(adapter), - mMeasurementsNotify(measurements) { - if (-1 != msInWeek) { - mAdapter.getAgcInformation(mMeasurementsNotify, msInWeek); - } - } - inline virtual void proc() const { - mAdapter.reportGnssMeasurementData(mMeasurementsNotify); - } - }; - - sendMsg(new MsgReportGnssMeasurementData(*this, measurements, msInWeek)); -} - -void -GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurements) -{ - for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { - if (nullptr != it->second.gnssMeasurementsCb) { - it->second.gnssMeasurementsCb(measurements); - } - } -} - -void -GnssAdapter::reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet) -{ - LOC_LOGD("%s]: ", __func__); - - // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary. - mUlpProxy->reportSvMeasurement(svMeasurementSet); -} - -void -GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial) -{ - LOC_LOGD("%s]: ", __func__); - - // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary. - mUlpProxy->reportSvPolynomial(svPolynomial); -} - -bool -GnssAdapter::reportOdcpiRequestEvent(OdcpiRequestInfo& request) -{ - struct MsgReportOdcpiRequest : public LocMsg { - GnssAdapter& mAdapter; - OdcpiRequestInfo mOdcpiRequest; - inline MsgReportOdcpiRequest(GnssAdapter& adapter, OdcpiRequestInfo& request) : - LocMsg(), - mAdapter(adapter), - mOdcpiRequest(request) {} - inline virtual void proc() const { - mAdapter.reportOdcpiRequest(mOdcpiRequest); - } - }; - - sendMsg(new MsgReportOdcpiRequest(*this, request)); - return true; -} - -void GnssAdapter::reportOdcpiRequest(const OdcpiRequestInfo& request) -{ - if (nullptr != mOdcpiRequestCb) { - LOC_LOGd("request: type %d, tbf %d, isEmergency %d" - " requestActive: %d timerActive: %d", - request.type, request.tbfMillis, request.isEmergencyMode, - mOdcpiRequestActive, mOdcpiTimer.isActive()); - // ODCPI START and ODCPI STOP from modem can come in quick succession - // so the mOdcpiTimer helps avoid spamming the framework as well as - // extending the odcpi session past 30 seconds if needed - if (ODCPI_REQUEST_TYPE_START == request.type) { - if (false == mOdcpiRequestActive && false == mOdcpiTimer.isActive()) { - mOdcpiRequestCb(request); - mOdcpiRequestActive = true; - mOdcpiTimer.start(); - // if the current active odcpi session is non-emergency, and the new - // odcpi request is emergency, replace the odcpi request with new request - // and restart the timer - } else if (false == mOdcpiRequest.isEmergencyMode && - true == request.isEmergencyMode) { - mOdcpiRequestCb(request); - mOdcpiRequestActive = true; - if (true == mOdcpiTimer.isActive()) { - mOdcpiTimer.restart(); - } else { - mOdcpiTimer.start(); - } - // if ODCPI request is not active but the timer is active, then - // just update the active state and wait for timer to expire - // before requesting new ODCPI to avoid spamming ODCPI requests - } else if (false == mOdcpiRequestActive && true == mOdcpiTimer.isActive()) { - mOdcpiRequestActive = true; - } - mOdcpiRequest = request; - // the request is being stopped, but allow timer to expire first - // before stopping the timer just in case more ODCPI requests come - // to avoid spamming more odcpi requests to the framework - } else { - mOdcpiRequestActive = false; - } - } else { - LOC_LOGw("ODCPI request not supported"); - } -} - -void GnssAdapter::initOdcpiCommand(const OdcpiRequestCallback& callback) -{ - struct MsgInitOdcpi : public LocMsg { - GnssAdapter& mAdapter; - OdcpiRequestCallback mOdcpiCb; - inline MsgInitOdcpi(GnssAdapter& adapter, - const OdcpiRequestCallback& callback) : - LocMsg(), - mAdapter(adapter), - mOdcpiCb(callback) {} - inline virtual void proc() const { - mAdapter.initOdcpi(mOdcpiCb); - } - }; - - sendMsg(new MsgInitOdcpi(*this, callback)); -} - -void GnssAdapter::initOdcpi(const OdcpiRequestCallback& callback) -{ - mOdcpiRequestCb = callback; - - /* Register for WIFI request */ - updateEvtMask(LOC_API_ADAPTER_BIT_REQUEST_WIFI, - LOC_REGISTRATION_MASK_ENABLED); -} - -void GnssAdapter::injectOdcpiCommand(const Location& location) -{ - struct MsgInjectOdcpi : public LocMsg { - GnssAdapter& mAdapter; - Location mLocation; - inline MsgInjectOdcpi(GnssAdapter& adapter, const Location& location) : - LocMsg(), - mAdapter(adapter), - mLocation(location) {} - inline virtual void proc() const { - mAdapter.injectOdcpi(mLocation); - } - }; - - sendMsg(new MsgInjectOdcpi(*this, location)); -} - -void GnssAdapter::injectOdcpi(const Location& location) -{ - LOC_LOGd("ODCPI Injection: requestActive: %d timerActive: %d" - "lat %.7f long %.7f", - mOdcpiRequestActive, mOdcpiTimer.isActive(), - location.latitude, location.longitude); - - loc_api_adapter_err err = mLocApi->injectPosition(location); - if (LOC_API_ADAPTER_ERR_SUCCESS != err) { - LOC_LOGe("Inject Position API error %d", err); - } -} - -// Called in the context of LocTimer thread -void OdcpiTimer::timeOutCallback() -{ - if (nullptr != mAdapter) { - mAdapter->odcpiTimerExpireEvent(); - } -} - -// Called in the context of LocTimer thread -void GnssAdapter::odcpiTimerExpireEvent() -{ - struct MsgOdcpiTimerExpire : public LocMsg { - GnssAdapter& mAdapter; - inline MsgOdcpiTimerExpire(GnssAdapter& adapter) : - LocMsg(), - mAdapter(adapter) {} - inline virtual void proc() const { - mAdapter.odcpiTimerExpire(); - } - }; - sendMsg(new MsgOdcpiTimerExpire(*this)); -} -void GnssAdapter::odcpiTimerExpire() -{ - LOC_LOGd("requestActive: %d timerActive: %d", - mOdcpiRequestActive, mOdcpiTimer.isActive()); - - // if ODCPI request is still active after timer - // expires, request again and restart timer - if (mOdcpiRequestActive) { - mOdcpiRequestCb(mOdcpiRequest); - mOdcpiTimer.restart(); - } else { - mOdcpiTimer.stop(); - } -} - -void GnssAdapter::initDefaultAgps() { - LOC_LOGD("%s]: ", __func__); - - void *handle = nullptr; - if ((handle = dlopen("libloc_net_iface.so", RTLD_NOW)) == nullptr) { - LOC_LOGD("%s]: libloc_net_iface.so not found !", __func__); - return; - } - - LocAgpsGetAgpsCbInfo getAgpsCbInfo = (LocAgpsGetAgpsCbInfo) - dlsym(handle, "LocNetIfaceAgps_getAgpsCbInfo"); - if (getAgpsCbInfo == nullptr) { - LOC_LOGE("%s]: Failed to get method LocNetIfaceAgps_getStatusCb", __func__); - return; - } - - AgpsCbInfo& cbInfo = getAgpsCbInfo(agpsOpenResultCb, agpsCloseResultCb, this); - - if (cbInfo.statusV4Cb == nullptr) { - LOC_LOGE("%s]: statusV4Cb is nullptr!", __func__); - return; - } - - initAgps(cbInfo); -} - -void GnssAdapter::initDefaultAgpsCommand() { - LOC_LOGD("%s]: ", __func__); - - struct MsgInitDefaultAgps : public LocMsg { - GnssAdapter& mAdapter; - inline MsgInitDefaultAgps(GnssAdapter& adapter) : - LocMsg(), - mAdapter(adapter) { - } - inline virtual void proc() const { - mAdapter.initDefaultAgps(); - } - }; - - sendMsg(new MsgInitDefaultAgps(*this)); -} - -/* INIT LOC AGPS MANAGER */ - -void GnssAdapter::initAgps(const AgpsCbInfo& cbInfo) { - LOC_LOGD("%s]: mAgpsCbInfo.cbPriority - %d; cbInfo.cbPriority - %d", - __func__, mAgpsCbInfo.cbPriority, cbInfo.cbPriority) - - if (!((ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSB) || - (ContextBase::mGps_conf.CAPABILITIES & LOC_GPS_CAPABILITY_MSA))) { - return; - } - - if (mAgpsCbInfo.cbPriority > cbInfo.cbPriority) { - return; - } else { - mAgpsCbInfo = cbInfo; - - mAgpsManager.registerFrameworkStatusCallback((AgnssStatusIpV4Cb)cbInfo.statusV4Cb); - - mAgpsManager.createAgpsStateMachines(); - - /* Register for AGPS event mask */ - updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST, - LOC_REGISTRATION_MASK_ENABLED); - } -} - -void GnssAdapter::initAgpsCommand(const AgpsCbInfo& cbInfo){ - LOC_LOGI("GnssAdapter::initAgpsCommand"); - - /* Message to initialize AGPS module */ - struct AgpsMsgInit: public LocMsg { - const AgpsCbInfo mCbInfo; - GnssAdapter& mAdapter; - - inline AgpsMsgInit(const AgpsCbInfo& cbInfo, - GnssAdapter& adapter) : - LocMsg(), mCbInfo(cbInfo), mAdapter(adapter) { - LOC_LOGV("AgpsMsgInit"); - } - - inline virtual void proc() const { - LOC_LOGV("AgpsMsgInit::proc()"); - mAdapter.initAgps(mCbInfo); - } - }; - - /* Send message to initialize AGPS Manager */ - sendMsg(new AgpsMsgInit(cbInfo, *this)); -} - -/* GnssAdapter::requestATL - * Method triggered in QMI thread as part of handling below message: - * eQMI_LOC_SERVER_REQUEST_OPEN_V02 - * Triggers the AGPS state machine to setup AGPS call for below WWAN types: - * eQMI_LOC_WWAN_TYPE_INTERNET_V02 - * eQMI_LOC_WWAN_TYPE_AGNSS_V02 */ -bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType){ - - LOC_LOGI("GnssAdapter::requestATL"); - - sendMsg( new AgpsMsgRequestATL( - &mAgpsManager, connHandle, (AGpsExtType)agpsType)); - - return true; -} - -/* GnssAdapter::requestSuplES - * Method triggered in QMI thread as part of handling below message: - * eQMI_LOC_SERVER_REQUEST_OPEN_V02 - * Triggers the AGPS state machine to setup AGPS call for below WWAN types: - * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */ -bool GnssAdapter::requestSuplES(int connHandle){ - - LOC_LOGI("GnssAdapter::requestSuplES"); - - sendMsg( new AgpsMsgRequestATL( - &mAgpsManager, connHandle, LOC_AGPS_TYPE_SUPL_ES)); - - return true; -} - -/* GnssAdapter::releaseATL - * Method triggered in QMI thread as part of handling below message: - * eQMI_LOC_SERVER_REQUEST_CLOSE_V02 - * Triggers teardown of an existing AGPS call */ -bool GnssAdapter::releaseATL(int connHandle){ - - LOC_LOGI("GnssAdapter::releaseATL"); - - /* Release SUPL/INTERNET/SUPL_ES ATL */ - struct AgpsMsgReleaseATL: public LocMsg { - - AgpsManager* mAgpsManager; - int mConnHandle; - - inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) : - LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) { - - LOC_LOGV("AgpsMsgReleaseATL"); - } - - inline virtual void proc() const { - - LOC_LOGV("AgpsMsgReleaseATL::proc()"); - mAgpsManager->releaseATL(mConnHandle); - } - }; - - sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle)); - - return true; -} - -/* GnssAdapter::reportDataCallOpened - * DS Client data call opened successfully. - * Send message to AGPS Manager to handle. */ -bool GnssAdapter::reportDataCallOpened(){ - - LOC_LOGI("GnssAdapter::reportDataCallOpened"); - - struct AgpsMsgSuplEsOpened: public LocMsg { - - AgpsManager* mAgpsManager; - - inline AgpsMsgSuplEsOpened(AgpsManager* agpsManager) : - LocMsg(), mAgpsManager(agpsManager) { - - LOC_LOGV("AgpsMsgSuplEsOpened"); - } - - inline virtual void proc() const { - - LOC_LOGV("AgpsMsgSuplEsOpened::proc()"); - mAgpsManager->reportDataCallOpened(); - } - }; - - sendMsg( new AgpsMsgSuplEsOpened(&mAgpsManager)); - - return true; -} - -/* GnssAdapter::reportDataCallClosed - * DS Client data call closed. - * Send message to AGPS Manager to handle. */ -bool GnssAdapter::reportDataCallClosed(){ - - LOC_LOGI("GnssAdapter::reportDataCallClosed"); - - struct AgpsMsgSuplEsClosed: public LocMsg { - - AgpsManager* mAgpsManager; - - inline AgpsMsgSuplEsClosed(AgpsManager* agpsManager) : - LocMsg(), mAgpsManager(agpsManager) { - - LOC_LOGV("AgpsMsgSuplEsClosed"); - } - - inline virtual void proc() const { - - LOC_LOGV("AgpsMsgSuplEsClosed::proc()"); - mAgpsManager->reportDataCallClosed(); - } - }; - - sendMsg( new AgpsMsgSuplEsClosed(&mAgpsManager)); - - return true; -} - -void GnssAdapter::dataConnOpenCommand( - AGpsExtType agpsType, - const char* apnName, int apnLen, AGpsBearerType bearerType){ - - LOC_LOGI("GnssAdapter::frameworkDataConnOpen"); - - struct AgpsMsgAtlOpenSuccess: public LocMsg { - - AgpsManager* mAgpsManager; - AGpsExtType mAgpsType; - char* mApnName; - int mApnLen; - AGpsBearerType mBearerType; - - inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType, - const char* apnName, int apnLen, AGpsBearerType bearerType) : - LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName( - new char[apnLen + 1]), mApnLen(apnLen), mBearerType(bearerType) { - - LOC_LOGV("AgpsMsgAtlOpenSuccess"); - if (mApnName == nullptr) { - LOC_LOGE("%s] new allocation failed, fatal error.", __func__); - return; - } - memcpy(mApnName, apnName, apnLen); - mApnName[apnLen] = 0; - } - - inline ~AgpsMsgAtlOpenSuccess() { - delete[] mApnName; - } - - inline virtual void proc() const { - - LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()"); - mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, mBearerType); - } - }; - - sendMsg( new AgpsMsgAtlOpenSuccess( - &mAgpsManager, agpsType, apnName, apnLen, bearerType)); -} - -void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){ - - LOC_LOGI("GnssAdapter::frameworkDataConnClosed"); - - struct AgpsMsgAtlClosed: public LocMsg { - - AgpsManager* mAgpsManager; - AGpsExtType mAgpsType; - - inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) : - LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) { - - LOC_LOGV("AgpsMsgAtlClosed"); - } - - inline virtual void proc() const { - - LOC_LOGV("AgpsMsgAtlClosed::proc()"); - mAgpsManager->reportAtlClosed(mAgpsType); - } - }; - - sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType)); -} - -void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){ - - LOC_LOGI("GnssAdapter::frameworkDataConnFailed"); - - struct AgpsMsgAtlOpenFailed: public LocMsg { - - AgpsManager* mAgpsManager; - AGpsExtType mAgpsType; - - inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) : - LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) { - - LOC_LOGV("AgpsMsgAtlOpenFailed"); - } - - inline virtual void proc() const { - - LOC_LOGV("AgpsMsgAtlOpenFailed::proc()"); - mAgpsManager->reportAtlOpenFailed(mAgpsType); - } - }; - - sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType)); -} - -void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out, - const GnssSvType& in_constellation, - const SystemStatusReports& in) -{ - uint64_t sv_mask = 0ULL; - uint32_t svid_min = 0; - uint32_t svid_num = 0; - uint32_t svid_idx = 0; - - uint64_t eph_health_good_mask = 0ULL; - uint64_t eph_health_bad_mask = 0ULL; - uint64_t server_perdiction_available_mask = 0ULL; - float server_perdiction_age = 0.0f; - - // set constellationi based parameters - switch (in_constellation) { - case GNSS_SV_TYPE_GPS: - svid_min = GNSS_BUGREPORT_GPS_MIN; - svid_num = GPS_NUM; - svid_idx = 0; - if (!in.mSvHealth.empty()) { - eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask; - eph_health_bad_mask = in.mSvHealth.back().mGpsBadMask; - } - if (!in.mXtra.empty()) { - server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid; - server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge); - } - break; - case GNSS_SV_TYPE_GLONASS: - svid_min = GNSS_BUGREPORT_GLO_MIN; - svid_num = GLO_NUM; - svid_idx = GPS_NUM; - if (!in.mSvHealth.empty()) { - eph_health_good_mask = in.mSvHealth.back().mGloGoodMask; - eph_health_bad_mask = in.mSvHealth.back().mGloBadMask; - } - if (!in.mXtra.empty()) { - server_perdiction_available_mask = in.mXtra.back().mGloXtraValid; - server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge); - } - break; - case GNSS_SV_TYPE_QZSS: - svid_min = GNSS_BUGREPORT_QZSS_MIN; - svid_num = QZSS_NUM; - svid_idx = GPS_NUM+GLO_NUM+BDS_NUM+GAL_NUM; - if (!in.mSvHealth.empty()) { - eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask; - eph_health_bad_mask = in.mSvHealth.back().mQzssBadMask; - } - if (!in.mXtra.empty()) { - server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid; - server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge); - } - break; - case GNSS_SV_TYPE_BEIDOU: - svid_min = GNSS_BUGREPORT_BDS_MIN; - svid_num = BDS_NUM; - svid_idx = GPS_NUM+GLO_NUM; - if (!in.mSvHealth.empty()) { - eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask; - eph_health_bad_mask = in.mSvHealth.back().mBdsBadMask; - } - if (!in.mXtra.empty()) { - server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid; - server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge); - } - break; - case GNSS_SV_TYPE_GALILEO: - svid_min = GNSS_BUGREPORT_GAL_MIN; - svid_num = GAL_NUM; - svid_idx = GPS_NUM+GLO_NUM+BDS_NUM; - if (!in.mSvHealth.empty()) { - eph_health_good_mask = in.mSvHealth.back().mGalGoodMask; - eph_health_bad_mask = in.mSvHealth.back().mGalBadMask; - } - if (!in.mXtra.empty()) { - server_perdiction_available_mask = in.mXtra.back().mGalXtraValid; - server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge); - } - break; - default: - return; - } - - // extract each sv info from systemstatus report - for(uint32_t i=0; i<svid_num && (svid_idx+i)<SV_ALL_NUM; i++) { - - GnssDebugSatelliteInfo s = {}; - s.size = sizeof(s); - s.svid = i + svid_min; - s.constellation = in_constellation; - - if (!in.mNavData.empty()) { - s.mEphemerisType = in.mNavData.back().mNav[svid_idx+i].mType; - s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource; - } - else { - s.mEphemerisType = GNSS_EPH_TYPE_UNKNOWN; - s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN; - } - - sv_mask = 0x1ULL << i; - if (eph_health_good_mask & sv_mask) { - s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD; - } - else if (eph_health_bad_mask & sv_mask) { - s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD; - } - else { - s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN; - } - - if (!in.mNavData.empty()) { - s.ephemerisAgeSeconds = - (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec); - } - else { - s.ephemerisAgeSeconds = 0.0f; - } - - if (server_perdiction_available_mask & sv_mask) { - s.serverPredictionIsAvailable = true; - } - else { - s.serverPredictionIsAvailable = false; - } - - s.serverPredictionAgeSeconds = server_perdiction_age; - out.push_back(s); - } - - return; -} - -bool GnssAdapter::getDebugReport(GnssDebugReport& r) -{ - LOC_LOGD("%s]: ", __func__); - - SystemStatus* systemstatus = getSystemStatus(); - if (nullptr == systemstatus) { - return false; - } - - SystemStatusReports reports = {}; - systemstatus->getReport(reports, true); - - r.size = sizeof(r); - - // location block - r.mLocation.size = sizeof(r.mLocation); - if(!reports.mLocation.empty() && reports.mLocation.back().mValid) { - r.mLocation.mValid = true; - r.mLocation.mLocation.latitude = - reports.mLocation.back().mLocation.gpsLocation.latitude; - r.mLocation.mLocation.longitude = - reports.mLocation.back().mLocation.gpsLocation.longitude; - r.mLocation.mLocation.altitude = - reports.mLocation.back().mLocation.gpsLocation.altitude; - r.mLocation.mLocation.speed = - (double)(reports.mLocation.back().mLocation.gpsLocation.speed); - r.mLocation.mLocation.bearing = - (double)(reports.mLocation.back().mLocation.gpsLocation.bearing); - r.mLocation.mLocation.accuracy = - (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy); - - r.mLocation.verticalAccuracyMeters = - reports.mLocation.back().mLocationEx.vert_unc; - r.mLocation.speedAccuracyMetersPerSecond = - reports.mLocation.back().mLocationEx.speed_unc; - r.mLocation.bearingAccuracyDegrees = - reports.mLocation.back().mLocationEx.bearing_unc; - - r.mLocation.mUtcReported = - reports.mLocation.back().mUtcReported; - } - else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) { - r.mLocation.mValid = true; - r.mLocation.mLocation.latitude = - (double)(reports.mBestPosition.back().mBestLat) * RAD2DEG; - r.mLocation.mLocation.longitude = - (double)(reports.mBestPosition.back().mBestLon) * RAD2DEG; - r.mLocation.mLocation.altitude = reports.mBestPosition.back().mBestAlt; - r.mLocation.mLocation.accuracy = - (double)(reports.mBestPosition.back().mBestHepe); - - r.mLocation.mUtcReported = reports.mBestPosition.back().mUtcReported; - } - else { - r.mLocation.mValid = false; - } - - if (r.mLocation.mValid) { - LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f", - r.mLocation.mLocation.latitude, - r.mLocation.mLocation.longitude, - r.mLocation.mLocation.altitude, - r.mLocation.mLocation.speed); - } - - // time block - r.mTime.size = sizeof(r.mTime); - if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) { - r.mTime.mValid = true; - r.mTime.timeEstimate = - (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 + - GNSS_UTC_TIME_OFFSET)*24*60*60 - - (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL + - (int64_t)(reports.mTimeAndClock.back().mGpsTowMs); - - r.mTime.timeUncertaintyNs = - ((float)(reports.mTimeAndClock.back().mTimeUnc) + - (float)(reports.mTimeAndClock.back().mLeapSecUnc))*1000.0f; - r.mTime.frequencyUncertaintyNsPerSec = - (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc); - LOC_LOGV("getDebugReport - timeestimate=%" PRIu64 " unc=%f frequnc=%f", - r.mTime.timeEstimate, - r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec); - } - else { - r.mTime.mValid = false; - } - - // satellite info block - convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports); - convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports); - convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports); - convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports); - convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports); - LOC_LOGV("getDebugReport - satellite=%zu", r.mSatelliteInfo.size()); - - return true; -} - -/* get AGC information from system status and fill it */ -void -GnssAdapter::getAgcInformation(GnssMeasurementsNotification& measurements, int msInWeek) -{ - SystemStatus* systemstatus = getSystemStatus(); - - if (nullptr != systemstatus) { - SystemStatusReports reports = {}; - systemstatus->getReport(reports, true); - - if ((!reports.mRfAndParams.empty()) && (!reports.mTimeAndClock.empty()) && - (abs(msInWeek - (int)reports.mTimeAndClock.back().mGpsTowMs) < 2000)) { - - for (size_t i = 0; i < measurements.count; i++) { - switch (measurements.measurements[i].svType) { - case GNSS_SV_TYPE_GPS: - case GNSS_SV_TYPE_QZSS: - measurements.measurements[i].agcLevelDb = - reports.mRfAndParams.back().mAgcGps; - measurements.measurements[i].flags |= - GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT; - break; - - case GNSS_SV_TYPE_GALILEO: - measurements.measurements[i].agcLevelDb = - reports.mRfAndParams.back().mAgcGal; - measurements.measurements[i].flags |= - GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT; - break; - - case GNSS_SV_TYPE_GLONASS: - measurements.measurements[i].agcLevelDb = - reports.mRfAndParams.back().mAgcGlo; - measurements.measurements[i].flags |= - GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT; - break; - - case GNSS_SV_TYPE_BEIDOU: - measurements.measurements[i].agcLevelDb = - reports.mRfAndParams.back().mAgcBds; - measurements.measurements[i].flags |= - GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT; - break; - - case GNSS_SV_TYPE_SBAS: - case GNSS_SV_TYPE_UNKNOWN: - default: - break; - } - } - } - } -} - -/* Callbacks registered with loc_net_iface library */ -static void agpsOpenResultCb (bool isSuccess, AGpsExtType agpsType, const char* apn, - AGpsBearerType bearerType, void* userDataPtr) { - LOC_LOGD("%s]: ", __func__); - if (userDataPtr == nullptr) { - LOC_LOGE("%s]: userDataPtr is nullptr.", __func__); - return; - } - if (apn == nullptr) { - LOC_LOGE("%s]: apn is nullptr.", __func__); - return; - } - GnssAdapter* adapter = (GnssAdapter*)userDataPtr; - if (isSuccess) { - adapter->dataConnOpenCommand(agpsType, apn, strlen(apn), bearerType); - } else { - adapter->dataConnFailedCommand(agpsType); - } -} - -static void agpsCloseResultCb (bool isSuccess, AGpsExtType agpsType, void* userDataPtr) { - LOC_LOGD("%s]: ", __func__); - if (userDataPtr == nullptr) { - LOC_LOGE("%s]: userDataPtr is nullptr.", __func__); - return; - } - GnssAdapter* adapter = (GnssAdapter*)userDataPtr; - if (isSuccess) { - adapter->dataConnClosedCommand(agpsType); - } else { - adapter->dataConnFailedCommand(agpsType); - } -} |