1/* Copyright (c) 2017, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions are 5 * met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation, nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29#define LOG_TAG "LocSvc_GnssAdapter" 30 31#include <sys/stat.h> 32#include <errno.h> 33#include <ctype.h> 34#include <cutils/properties.h> 35#include <math.h> 36#include <arpa/inet.h> 37#include <netinet/in.h> 38#include <netdb.h> 39#include <GnssAdapter.h> 40#include <string> 41#include <loc_log.h> 42#include <loc_nmea.h> 43#include <Agps.h> 44#include <SystemStatus.h> 45 46#include <loc_nmea.h> 47#include <vector> 48#include <string> 49 50using namespace loc_core; 51 52GnssAdapter::GnssAdapter() : 53 LocAdapterBase(0, 54 LocDualContext::getLocFgContext(NULL, 55 NULL, 56 LocDualContext::mLocationHalName, 57 false)), 58 mUlpProxy(new UlpProxyBase()), 59 mUlpPositionMode(), 60 mGnssSvIdUsedInPosition(), 61 mGnssSvIdUsedInPosAvail(false), 62 mControlCallbacks(), 63 mPowerVoteId(0), 64 mNiData(), 65 mAgpsManager() 66{ 67 LOC_LOGD("%s]: Constructor %p", __func__, this); 68 mUlpPositionMode.mode = LOC_POSITION_MODE_INVALID; 69 readConfigCommand(); 70 setConfigCommand(); 71 72} 73 74inline 75GnssAdapter::~GnssAdapter() 76{ 77 LOC_LOGD("%s]: Destructor", __func__); 78 delete mUlpProxy; 79} 80 81void 82GnssAdapter::setControlCallbacksCommand(LocationControlCallbacks& controlCallbacks) 83{ 84 struct MsgSetControlCallbacks : public LocMsg { 85 GnssAdapter& mAdapter; 86 const LocationControlCallbacks mControlCallbacks; 87 inline MsgSetControlCallbacks(GnssAdapter& adapter, 88 LocationControlCallbacks& controlCallbacks) : 89 LocMsg(), 90 mAdapter(adapter), 91 mControlCallbacks(controlCallbacks) {} 92 inline virtual void proc() const { 93 mAdapter.setControlCallbacks(mControlCallbacks); 94 } 95 }; 96 97 sendMsg(new MsgSetControlCallbacks(*this, controlCallbacks)); 98} 99 100void 101GnssAdapter::convertOptions(LocPosMode& out, const LocationOptions& options) 102{ 103 LocPosMode locPosMode = {}; 104 switch (options.mode) { 105 case GNSS_SUPL_MODE_MSB: 106 out.mode = LOC_POSITION_MODE_MS_BASED; 107 break; 108 case GNSS_SUPL_MODE_MSA: 109 out.mode = LOC_POSITION_MODE_MS_ASSISTED; 110 break; 111 default: 112 out.mode = LOC_POSITION_MODE_STANDALONE; 113 break; 114 } 115 out.share_position = true; 116 out.min_interval = options.minInterval; 117} 118 119void 120GnssAdapter::convertLocation(Location& out, const LocGpsLocation& locGpsLocation, 121 const GpsLocationExtended& locationExtended, 122 const LocPosTechMask techMask) 123{ 124 out.size = sizeof(Location); 125 if (LOC_GPS_LOCATION_HAS_LAT_LONG & locGpsLocation.flags) { 126 out.flags |= LOCATION_HAS_LAT_LONG_BIT; 127 out.latitude = locGpsLocation.latitude; 128 out.longitude = locGpsLocation.longitude; 129 } 130 if (LOC_GPS_LOCATION_HAS_ALTITUDE & locGpsLocation.flags) { 131 out.flags |= LOCATION_HAS_ALTITUDE_BIT; 132 out.altitude = locGpsLocation.altitude; 133 } 134 if (LOC_GPS_LOCATION_HAS_SPEED & locGpsLocation.flags) { 135 out.flags |= LOCATION_HAS_SPEED_BIT; 136 out.speed = locGpsLocation.speed; 137 } 138 if (LOC_GPS_LOCATION_HAS_BEARING & locGpsLocation.flags) { 139 out.flags |= LOCATION_HAS_BEARING_BIT; 140 out.bearing = locGpsLocation.bearing; 141 } 142 if (LOC_GPS_LOCATION_HAS_ACCURACY & locGpsLocation.flags) { 143 out.flags |= LOCATION_HAS_ACCURACY_BIT; 144 out.accuracy = locGpsLocation.accuracy; 145 } 146 if (GPS_LOCATION_EXTENDED_HAS_VERT_UNC & locationExtended.flags) { 147 out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT; 148 out.verticalAccuracy = locationExtended.vert_unc; 149 } 150 if (GPS_LOCATION_EXTENDED_HAS_SPEED_UNC & locationExtended.flags) { 151 out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT; 152 out.speedAccuracy = locationExtended.speed_unc; 153 } 154 if (GPS_LOCATION_EXTENDED_HAS_BEARING_UNC & locationExtended.flags) { 155 out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT; 156 out.bearingAccuracy = locationExtended.bearing_unc; 157 } 158 out.timestamp = locGpsLocation.timestamp; 159 if (LOC_POS_TECH_MASK_SATELLITE & techMask) { 160 out.techMask |= LOCATION_TECHNOLOGY_GNSS_BIT; 161 } 162 if (LOC_POS_TECH_MASK_CELLID & techMask) { 163 out.techMask |= LOCATION_TECHNOLOGY_CELL_BIT; 164 } 165 if (LOC_POS_TECH_MASK_WIFI & techMask) { 166 out.techMask |= LOCATION_TECHNOLOGY_WIFI_BIT; 167 } 168 if (LOC_POS_TECH_MASK_SENSORS & techMask) { 169 out.techMask |= LOCATION_TECHNOLOGY_SENSORS_BIT; 170 } 171} 172 173void 174GnssAdapter::convertLocationInfo(GnssLocationInfoNotification& out, 175 const GpsLocationExtended& locationExtended) 176{ 177 out.size = sizeof(GnssLocationInfoNotification); 178 if (GPS_LOCATION_EXTENDED_HAS_ALTITUDE_MEAN_SEA_LEVEL & locationExtended.flags) { 179 out.flags |= GNSS_LOCATION_INFO_ALTITUDE_MEAN_SEA_LEVEL_BIT; 180 out.altitudeMeanSeaLevel = locationExtended.altitudeMeanSeaLevel; 181 } 182 if (GPS_LOCATION_EXTENDED_HAS_DOP & locationExtended.flags) { 183 out.flags |= GNSS_LOCATION_INFO_DOP_BIT; 184 out.pdop = locationExtended.pdop; 185 out.hdop = locationExtended.hdop; 186 out.vdop = locationExtended.vdop; 187 } 188 if (GPS_LOCATION_EXTENDED_HAS_MAG_DEV & locationExtended.flags) { 189 out.flags |= GNSS_LOCATION_INFO_MAGNETIC_DEVIATION_BIT; 190 out.magneticDeviation = locationExtended.magneticDeviation; 191 } 192 if (GPS_LOCATION_EXTENDED_HAS_HOR_RELIABILITY & locationExtended.flags) { 193 out.flags |= GNSS_LOCATION_INFO_HOR_RELIABILITY_BIT; 194 switch (locationExtended.horizontal_reliability) { 195 case LOC_RELIABILITY_VERY_LOW: 196 out.horReliability = LOCATION_RELIABILITY_VERY_LOW; 197 break; 198 case LOC_RELIABILITY_LOW: 199 out.horReliability = LOCATION_RELIABILITY_LOW; 200 break; 201 case LOC_RELIABILITY_MEDIUM: 202 out.horReliability = LOCATION_RELIABILITY_MEDIUM; 203 break; 204 case LOC_RELIABILITY_HIGH: 205 out.horReliability = LOCATION_RELIABILITY_HIGH; 206 break; 207 default: 208 out.horReliability = LOCATION_RELIABILITY_NOT_SET; 209 break; 210 } 211 } 212 if (GPS_LOCATION_EXTENDED_HAS_VERT_RELIABILITY & locationExtended.flags) { 213 out.flags |= GNSS_LOCATION_INFO_VER_RELIABILITY_BIT; 214 switch (locationExtended.vertical_reliability) { 215 case LOC_RELIABILITY_VERY_LOW: 216 out.verReliability = LOCATION_RELIABILITY_VERY_LOW; 217 break; 218 case LOC_RELIABILITY_LOW: 219 out.verReliability = LOCATION_RELIABILITY_LOW; 220 break; 221 case LOC_RELIABILITY_MEDIUM: 222 out.verReliability = LOCATION_RELIABILITY_MEDIUM; 223 break; 224 case LOC_RELIABILITY_HIGH: 225 out.verReliability = LOCATION_RELIABILITY_HIGH; 226 break; 227 default: 228 out.verReliability = LOCATION_RELIABILITY_NOT_SET; 229 break; 230 } 231 } 232 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MAJOR & locationExtended.flags) { 233 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MAJOR_BIT; 234 out.horUncEllipseSemiMajor = locationExtended.horUncEllipseSemiMajor; 235 } 236 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_MINOR & locationExtended.flags) { 237 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_SEMI_MINOR_BIT; 238 out.horUncEllipseSemiMinor = locationExtended.horUncEllipseSemiMinor; 239 } 240 if (GPS_LOCATION_EXTENDED_HAS_HOR_ELIP_UNC_AZIMUTH & locationExtended.flags) { 241 out.flags |= GNSS_LOCATION_INFO_HOR_ACCURACY_ELIP_AZIMUTH_BIT; 242 out.horUncEllipseOrientAzimuth = locationExtended.horUncEllipseOrientAzimuth; 243 } 244} 245 246inline uint32_t 247GnssAdapter::convertGpsLock(const GnssConfigGpsLock gpsLock) 248{ 249 switch (gpsLock) { 250 case GNSS_CONFIG_GPS_LOCK_MO: 251 return 1; 252 case GNSS_CONFIG_GPS_LOCK_NI: 253 return 2; 254 case GNSS_CONFIG_GPS_LOCK_MO_AND_NI: 255 return 3; 256 case GNSS_CONFIG_GPS_LOCK_NONE: 257 default: 258 return 0; 259 } 260} 261 262inline GnssConfigGpsLock 263GnssAdapter::convertGpsLock(const uint32_t gpsLock) 264{ 265 switch (gpsLock) { 266 case 1: 267 return GNSS_CONFIG_GPS_LOCK_MO; 268 case 2: 269 return GNSS_CONFIG_GPS_LOCK_NI; 270 case 3: 271 return GNSS_CONFIG_GPS_LOCK_MO_AND_NI; 272 case 0: 273 default: 274 return GNSS_CONFIG_GPS_LOCK_NONE; 275 } 276} 277 278inline uint32_t 279GnssAdapter::convertSuplVersion(const GnssConfigSuplVersion suplVersion) 280{ 281 switch (suplVersion) { 282 case GNSS_CONFIG_SUPL_VERSION_2_0_0: 283 return 0x00020000; 284 case GNSS_CONFIG_SUPL_VERSION_2_0_2: 285 return 0x00020002; 286 case GNSS_CONFIG_SUPL_VERSION_1_0_0: 287 default: 288 return 0x00010000; 289 } 290} 291 292inline GnssConfigSuplVersion 293GnssAdapter::convertSuplVersion(const uint32_t suplVersion) 294{ 295 switch (suplVersion) { 296 case 0x00020000: 297 return GNSS_CONFIG_SUPL_VERSION_2_0_0; 298 case 0x00020002: 299 return GNSS_CONFIG_SUPL_VERSION_2_0_2; 300 case 0x00010000: 301 default: 302 return GNSS_CONFIG_SUPL_VERSION_1_0_0; 303 } 304} 305 306inline uint32_t 307GnssAdapter::convertLppProfile(const GnssConfigLppProfile lppProfile) 308{ 309 switch (lppProfile) { 310 case GNSS_CONFIG_LPP_PROFILE_USER_PLANE: 311 return 1; 312 case GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE: 313 return 2; 314 case GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE: 315 return 3; 316 case GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE: 317 default: 318 return 0; 319 } 320} 321 322inline GnssConfigLppProfile 323GnssAdapter::convertLppProfile(const uint32_t lppProfile) 324{ 325 switch (lppProfile) { 326 case 1: 327 return GNSS_CONFIG_LPP_PROFILE_USER_PLANE; 328 case 2: 329 return GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE; 330 case 3: 331 return GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE; 332 case 0: 333 default: 334 return GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; 335 } 336} 337 338uint32_t 339GnssAdapter::convertLppeCp(const GnssConfigLppeControlPlaneMask lppeControlPlaneMask) 340{ 341 uint32_t mask = 0; 342 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT & lppeControlPlaneMask) { 343 mask |= (1<<0); 344 } 345 if (GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeControlPlaneMask) { 346 mask |= (1<<1); 347 } 348 return mask; 349} 350 351GnssConfigLppeControlPlaneMask 352GnssAdapter::convertLppeCp(const uint32_t lppeControlPlaneMask) 353{ 354 GnssConfigLppeControlPlaneMask mask = 0; 355 if ((1<<0) & lppeControlPlaneMask) { 356 mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_DBH_BIT; 357 } 358 if ((1<<1) & lppeControlPlaneMask) { 359 mask |= GNSS_CONFIG_LPPE_CONTROL_PLANE_WLAN_AP_MEASUREMENTS_BIT; 360 } 361 return mask; 362} 363 364 365uint32_t 366GnssAdapter::convertLppeUp(const GnssConfigLppeUserPlaneMask lppeUserPlaneMask) 367{ 368 uint32_t mask = 0; 369 if (GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT & lppeUserPlaneMask) { 370 mask |= (1<<0); 371 } 372 if (GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT & lppeUserPlaneMask) { 373 mask |= (1<<1); 374 } 375 return mask; 376} 377 378GnssConfigLppeUserPlaneMask 379GnssAdapter::convertLppeUp(const uint32_t lppeUserPlaneMask) 380{ 381 GnssConfigLppeUserPlaneMask mask = 0; 382 if ((1<<0) & lppeUserPlaneMask) { 383 mask |= GNSS_CONFIG_LPPE_USER_PLANE_DBH_BIT; 384 } 385 if ((1<<1) & lppeUserPlaneMask) { 386 mask |= GNSS_CONFIG_LPPE_USER_PLANE_WLAN_AP_MEASUREMENTS_BIT; 387 } 388 return mask; 389} 390 391uint32_t 392GnssAdapter::convertAGloProt(const GnssConfigAGlonassPositionProtocolMask aGloPositionProtocolMask) 393{ 394 uint32_t mask = 0; 395 if (GNSS_CONFIG_RRC_CONTROL_PLANE_BIT & aGloPositionProtocolMask) { 396 mask |= (1<<0); 397 } 398 if (GNSS_CONFIG_RRLP_USER_PLANE_BIT & aGloPositionProtocolMask) { 399 mask |= (1<<1); 400 } 401 if (GNSS_CONFIG_LLP_USER_PLANE_BIT & aGloPositionProtocolMask) { 402 mask |= (1<<2); 403 } 404 if (GNSS_CONFIG_LLP_CONTROL_PLANE_BIT & aGloPositionProtocolMask) { 405 mask |= (1<<3); 406 } 407 return mask; 408} 409 410uint32_t 411GnssAdapter::convertEP4ES(const GnssConfigEmergencyPdnForEmergencySupl emergencyPdnForEmergencySupl) 412{ 413 switch (emergencyPdnForEmergencySupl) { 414 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES: 415 return 1; 416 case GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO: 417 default: 418 return 0; 419 } 420} 421 422uint32_t 423GnssAdapter::convertSuplEs(const GnssConfigSuplEmergencyServices suplEmergencyServices) 424{ 425 switch (suplEmergencyServices) { 426 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES: 427 return 1; 428 case GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO: 429 default: 430 return 0; 431 } 432} 433 434uint32_t 435GnssAdapter::convertSuplMode(const GnssConfigSuplModeMask suplModeMask) 436{ 437 uint32_t mask = 0; 438 if (GNSS_CONFIG_SUPL_MODE_MSB_BIT & suplModeMask) { 439 mask |= (1<<0); 440 } 441 if (GNSS_CONFIG_SUPL_MODE_MSA_BIT & suplModeMask) { 442 mask |= (1<<1); 443 } 444 return mask; 445} 446 447bool 448GnssAdapter::resolveInAddress(const char* hostAddress, struct in_addr* inAddress) 449{ 450 bool ret = true; 451 452 struct hostent* hp; 453 hp = gethostbyname(hostAddress); 454 if (hp != NULL) { /* DNS OK */ 455 memcpy(inAddress, hp->h_addr_list[0], hp->h_length); 456 } else { 457 /* Try IP representation */ 458 if (inet_aton(hostAddress, inAddress) == 0) { 459 /* IP not valid */ 460 LOC_LOGE("%s]: DNS query on '%s' failed", __func__, hostAddress); 461 ret = false; 462 } 463 } 464 465 return ret; 466} 467 468void 469GnssAdapter::readConfigCommand() 470{ 471 LOC_LOGD("%s]: ", __func__); 472 473 struct MsgReadConfig : public LocMsg { 474 GnssAdapter* mAdapter; 475 ContextBase& mContext; 476 inline MsgReadConfig(GnssAdapter* adapter, 477 ContextBase& context) : 478 LocMsg(), 479 mAdapter(adapter), 480 mContext(context) {} 481 inline virtual void proc() const { 482 // reads config into mContext->mGps_conf 483 mContext.readConfig(); 484 mContext.requestUlp((LocAdapterBase*)mAdapter, mContext.getCarrierCapabilities()); 485 } 486 }; 487 488 if (mContext != NULL) { 489 sendMsg(new MsgReadConfig(this, *mContext)); 490 } 491} 492 493void 494GnssAdapter::setConfigCommand() 495{ 496 LOC_LOGD("%s]: ", __func__); 497 498 struct MsgSetConfig : public LocMsg { 499 GnssAdapter& mAdapter; 500 LocApiBase& mApi; 501 inline MsgSetConfig(GnssAdapter& adapter, 502 LocApiBase& api) : 503 LocMsg(), 504 mAdapter(adapter), 505 mApi(api) {} 506 inline virtual void proc() const { 507 if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { 508 mApi.setSUPLVersion(mAdapter.convertSuplVersion(ContextBase::mGps_conf.SUPL_VER)); 509 mApi.setLPPConfig(mAdapter.convertLppProfile(ContextBase::mGps_conf.LPP_PROFILE)); 510 mApi.setAGLONASSProtocol(ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT); 511 } 512 mApi.setSensorControlConfig(ContextBase::mSap_conf.SENSOR_USAGE, 513 ContextBase::mSap_conf.SENSOR_PROVIDER); 514 mApi.setLPPeProtocolCp( 515 mAdapter.convertLppeCp(ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY)); 516 mApi.setLPPeProtocolUp( 517 mAdapter.convertLppeUp(ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY)); 518 519 // set nmea mask type 520 uint32_t mask = 0; 521 if (NMEA_PROVIDER_MP == ContextBase::mGps_conf.NMEA_PROVIDER) { 522 mask = LOC_NMEA_ALL_SUPPORTED_MASK; 523 } else { 524 mask = LOC_NMEA_MASK_DEBUG_V02; 525 } 526 mApi.setNMEATypes(mask); 527 528 mApi.setXtraVersionCheck(ContextBase::mGps_conf.XTRA_VERSION_CHECK); 529 if (ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID || 530 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID || 531 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID || 532 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID || 533 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID ) { 534 mApi.setSensorProperties( 535 ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK_VALID, 536 ContextBase::mSap_conf.GYRO_BIAS_RANDOM_WALK, 537 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 538 ContextBase::mSap_conf.ACCEL_RANDOM_WALK_SPECTRAL_DENSITY, 539 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 540 ContextBase::mSap_conf.ANGLE_RANDOM_WALK_SPECTRAL_DENSITY, 541 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 542 ContextBase::mSap_conf.RATE_RANDOM_WALK_SPECTRAL_DENSITY, 543 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY_VALID, 544 ContextBase::mSap_conf.VELOCITY_RANDOM_WALK_SPECTRAL_DENSITY); 545 } 546 mApi.setSensorPerfControlConfig( 547 ContextBase::mSap_conf.SENSOR_CONTROL_MODE, 548 ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH, 549 ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC, 550 ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH, 551 ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC, 552 ContextBase::mSap_conf.SENSOR_ACCEL_SAMPLES_PER_BATCH_HIGH, 553 ContextBase::mSap_conf.SENSOR_ACCEL_BATCHES_PER_SEC_HIGH, 554 ContextBase::mSap_conf.SENSOR_GYRO_SAMPLES_PER_BATCH_HIGH, 555 ContextBase::mSap_conf.SENSOR_GYRO_BATCHES_PER_SEC_HIGH, 556 ContextBase::mSap_conf.SENSOR_ALGORITHM_CONFIG_MASK); 557 } 558 }; 559 560 sendMsg(new MsgSetConfig(*this, *mLocApi)); 561} 562 563uint32_t* 564GnssAdapter::gnssUpdateConfigCommand(GnssConfig config) 565{ 566 // count the number of bits set 567 GnssConfigFlagsMask flagsCopy = config.flags; 568 size_t count = 0; 569 while (flagsCopy > 0) { 570 if (flagsCopy & 1) { 571 count++; 572 } 573 flagsCopy >>= 1; 574 } 575 std::string idsString = "["; 576 uint32_t* ids = NULL; 577 if (count > 0) { 578 ids = new uint32_t[count]; 579 for (size_t i=0; i < count; ++i) { 580 ids[i] = generateSessionId(); 581 IF_LOC_LOGD { 582 idsString += std::to_string(ids[i]) + " "; 583 } 584 } 585 } 586 idsString += "]"; 587 588 LOC_LOGD("%s]: ids %s flags 0x%X", __func__, idsString.c_str(), config.flags); 589 590 struct MsgGnssUpdateConfig : public LocMsg { 591 GnssAdapter& mAdapter; 592 LocApiBase& mApi; 593 GnssConfig mConfig; 594 uint32_t* mIds; 595 size_t mCount; 596 inline MsgGnssUpdateConfig(GnssAdapter& adapter, 597 LocApiBase& api, 598 GnssConfig config, 599 uint32_t* ids, 600 size_t count) : 601 LocMsg(), 602 mAdapter(adapter), 603 mApi(api), 604 mConfig(config), 605 mIds(ids), 606 mCount(count) {} 607 inline virtual ~MsgGnssUpdateConfig() 608 { 609 delete[] mIds; 610 } 611 inline virtual void proc() const { 612 //const size_t MAX_BITS_COUNT = 10; 613 //LocationError errs[MAX_BITS_COUNT] = {}; 614 LocationError* errs = new LocationError[mCount]; 615 LocationError err = LOCATION_ERROR_SUCCESS; 616 uint32_t index = 0; 617 618 if (mConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) { 619 uint32_t newGpsLock = mAdapter.convertGpsLock(mConfig.gpsLock); 620 ContextBase::mGps_conf.GPS_LOCK = newGpsLock; 621 if (0 == mAdapter.getPowerVoteId()) { 622 err = mApi.setGpsLock(mConfig.gpsLock); 623 } 624 if (index < mCount) { 625 errs[index++] = err; 626 } 627 } 628 if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) { 629 uint32_t newSuplVersion = mAdapter.convertSuplVersion(mConfig.suplVersion); 630 if (newSuplVersion != ContextBase::mGps_conf.SUPL_VER && 631 ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { 632 ContextBase::mGps_conf.SUPL_VER = newSuplVersion; 633 err = mApi.setSUPLVersion(mConfig.suplVersion); 634 } else { 635 err = LOCATION_ERROR_SUCCESS; 636 } 637 if (index < mCount) { 638 errs[index++] = err; 639 } 640 } 641 if (mConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) { 642 if (GNSS_ASSISTANCE_TYPE_SUPL == mConfig.assistanceServer.type) { 643 if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { 644 char serverUrl[MAX_URL_LEN] = {}; 645 uint32_t length = 0; 646 const char noHost[] = "NONE"; 647 if (NULL == mConfig.assistanceServer.hostName || 648 strncasecmp(noHost, 649 mConfig.assistanceServer.hostName, 650 sizeof(noHost)) == 0) { 651 } else { 652 length = snprintf(serverUrl, sizeof(serverUrl), "%s:%u", 653 mConfig.assistanceServer.hostName, 654 mConfig.assistanceServer.port); 655 } 656 657 if (sizeof(serverUrl) > length) { 658 err = mApi.setServer(serverUrl, length); 659 } else { 660 err = LOCATION_ERROR_INVALID_PARAMETER; 661 } 662 } else { 663 err = LOCATION_ERROR_SUCCESS; 664 } 665 } else if (GNSS_ASSISTANCE_TYPE_C2K == mConfig.assistanceServer.type) { 666 if (ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { 667 struct in_addr addr; 668 if (!mAdapter.resolveInAddress(mConfig.assistanceServer.hostName, &addr)) { 669 LOC_LOGE("%s]: hostName %s cannot be resolved", 670 __func__, mConfig.assistanceServer.hostName); 671 err = LOCATION_ERROR_INVALID_PARAMETER; 672 } else { 673 unsigned int ip = htonl(addr.s_addr); 674 err = mApi.setServer(ip, mConfig.assistanceServer.port, 675 LOC_AGPS_CDMA_PDE_SERVER); 676 } 677 } else { 678 err = LOCATION_ERROR_SUCCESS; 679 } 680 } else { 681 LOC_LOGE("%s]: Not a valid gnss assistance type %u", 682 __func__, mConfig.assistanceServer.type); 683 err = LOCATION_ERROR_INVALID_PARAMETER; 684 } 685 if (index < mCount) { 686 errs[index++] = err; 687 } 688 } 689 if (mConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) { 690 uint32_t newLppProfile = mAdapter.convertLppProfile(mConfig.lppProfile); 691 if (newLppProfile != ContextBase::mGps_conf.LPP_PROFILE && 692 ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { 693 ContextBase::mGps_conf.LPP_PROFILE = newLppProfile; 694 err = mApi.setLPPConfig(mConfig.lppProfile); 695 } else { 696 err = LOCATION_ERROR_SUCCESS; 697 } 698 if (index < mCount) { 699 errs[index++] = err; 700 } 701 } 702 if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) { 703 uint32_t newLppeControlPlaneMask = 704 mAdapter.convertLppeCp(mConfig.lppeControlPlaneMask); 705 if (newLppeControlPlaneMask != ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY) { 706 ContextBase::mGps_conf.LPPE_CP_TECHNOLOGY = newLppeControlPlaneMask; 707 err = mApi.setLPPeProtocolCp(mConfig.lppeControlPlaneMask); 708 } else { 709 err = LOCATION_ERROR_SUCCESS; 710 } 711 if (index < mCount) { 712 errs[index++] = err; 713 } 714 } 715 if (mConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) { 716 uint32_t newLppeUserPlaneMask = 717 mAdapter.convertLppeUp(mConfig.lppeUserPlaneMask); 718 if (newLppeUserPlaneMask != ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY) { 719 ContextBase::mGps_conf.LPPE_UP_TECHNOLOGY = newLppeUserPlaneMask; 720 err = mApi.setLPPeProtocolUp(mConfig.lppeUserPlaneMask); 721 } else { 722 err = LOCATION_ERROR_SUCCESS; 723 } 724 if (index < mCount) { 725 errs[index++] = err; 726 } 727 } 728 if (mConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) { 729 uint32_t newAGloProtMask = 730 mAdapter.convertAGloProt(mConfig.aGlonassPositionProtocolMask); 731 if (newAGloProtMask != ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT && 732 ContextBase::mGps_conf.AGPS_CONFIG_INJECT) { 733 ContextBase::mGps_conf.A_GLONASS_POS_PROTOCOL_SELECT = newAGloProtMask; 734 err = mApi.setAGLONASSProtocol(mConfig.aGlonassPositionProtocolMask); 735 } else { 736 err = LOCATION_ERROR_SUCCESS; 737 } 738 if (index < mCount) { 739 errs[index++] = err; 740 } 741 } 742 if (mConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) { 743 uint32_t newEP4ES = mAdapter.convertEP4ES(mConfig.emergencyPdnForEmergencySupl); 744 if (newEP4ES != ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL) { 745 ContextBase::mGps_conf.USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL = newEP4ES; 746 } 747 err = LOCATION_ERROR_SUCCESS; 748 if (index < mCount) { 749 errs[index++] = err; 750 } 751 } 752 if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) { 753 uint32_t newSuplEs = mAdapter.convertSuplEs(mConfig.suplEmergencyServices); 754 if (newSuplEs != ContextBase::mGps_conf.SUPL_ES) { 755 ContextBase::mGps_conf.SUPL_ES = newSuplEs; 756 } 757 err = LOCATION_ERROR_SUCCESS; 758 if (index < mCount) { 759 errs[index++] = err; 760 } 761 } 762 if (mConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) { 763 uint32_t newSuplMode = mAdapter.convertSuplMode(mConfig.suplModeMask); 764 if (newSuplMode != ContextBase::mGps_conf.SUPL_MODE) { 765 ContextBase::mGps_conf.SUPL_MODE = newSuplMode; 766 mAdapter.getUlpProxy()->setCapabilities( 767 ContextBase::getCarrierCapabilities()); 768 } 769 err = LOCATION_ERROR_SUCCESS; 770 if (index < mCount) { 771 errs[index++] = err; 772 } 773 } 774 775 mAdapter.reportResponse(index, errs, mIds); 776 delete[] errs; 777 } 778 }; 779 780 if (NULL != ids) { 781 sendMsg(new MsgGnssUpdateConfig(*this, *mLocApi, config, ids, count)); 782 } else { 783 LOC_LOGE("%s]: No GNSS config items to update", __func__); 784 } 785 786 return ids; 787} 788 789uint32_t 790GnssAdapter::gnssDeleteAidingDataCommand(GnssAidingData& data) 791{ 792 uint32_t sessionId = generateSessionId(); 793 LOC_LOGD("%s]: id %u", __func__, sessionId); 794 795 struct MsgDeleteAidingData : public LocMsg { 796 GnssAdapter& mAdapter; 797 LocApiBase& mApi; 798 uint32_t mSessionId; 799 GnssAidingData mData; 800 inline MsgDeleteAidingData(GnssAdapter& adapter, 801 LocApiBase& api, 802 uint32_t sessionId, 803 GnssAidingData& data) : 804 LocMsg(), 805 mAdapter(adapter), 806 mApi(api), 807 mSessionId(sessionId), 808 mData(data) {} 809 inline virtual void proc() const { 810 LocationError err = LOCATION_ERROR_SUCCESS; 811 err = mApi.deleteAidingData(mData); 812 mAdapter.reportResponse(err, mSessionId); 813 } 814 }; 815 816 sendMsg(new MsgDeleteAidingData(*this, *mLocApi, sessionId, data)); 817 return sessionId; 818} 819 820void 821GnssAdapter::injectLocationCommand(double latitude, double longitude, float accuracy) 822{ 823 LOC_LOGD("%s]: latitude %8.4f longitude %8.4f accuracy %8.4f", 824 __func__, latitude, longitude, accuracy); 825 826 struct MsgInjectLocation : public LocMsg { 827 LocApiBase& mApi; 828 ContextBase& mContext; 829 double mLatitude; 830 double mLongitude; 831 float mAccuracy; 832 inline MsgInjectLocation(LocApiBase& api, 833 ContextBase& context, 834 double latitude, 835 double longitude, 836 float accuracy) : 837 LocMsg(), 838 mApi(api), 839 mContext(context), 840 mLatitude(latitude), 841 mLongitude(longitude), 842 mAccuracy(accuracy) {} 843 inline virtual void proc() const { 844 if (!mContext.hasCPIExtendedCapabilities()) { 845 mApi.injectPosition(mLatitude, mLongitude, mAccuracy); 846 } 847 } 848 }; 849 850 sendMsg(new MsgInjectLocation(*mLocApi, *mContext, latitude, longitude, accuracy)); 851} 852 853void 854GnssAdapter::injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty) 855{ 856 LOC_LOGD("%s]: time %lld timeReference %lld uncertainty %d", 857 __func__, (long long)time, (long long)timeReference, uncertainty); 858 859 struct MsgInjectTime : public LocMsg { 860 LocApiBase& mApi; 861 ContextBase& mContext; 862 int64_t mTime; 863 int64_t mTimeReference; 864 int32_t mUncertainty; 865 inline MsgInjectTime(LocApiBase& api, 866 ContextBase& context, 867 int64_t time, 868 int64_t timeReference, 869 int32_t uncertainty) : 870 LocMsg(), 871 mApi(api), 872 mContext(context), 873 mTime(time), 874 mTimeReference(timeReference), 875 mUncertainty(uncertainty) {} 876 inline virtual void proc() const { 877 mApi.setTime(mTime, mTimeReference, mUncertainty); 878 } 879 }; 880 881 sendMsg(new MsgInjectTime(*mLocApi, *mContext, time, timeReference, uncertainty)); 882} 883 884void 885GnssAdapter::setUlpProxyCommand(UlpProxyBase* ulp) 886{ 887 LOC_LOGD("%s]: ", __func__); 888 889 struct MsgSetUlpProxy : public LocMsg { 890 GnssAdapter& mAdapter; 891 UlpProxyBase* mUlp; 892 inline MsgSetUlpProxy(GnssAdapter& adapter, 893 UlpProxyBase* ulp) : 894 LocMsg(), 895 mAdapter(adapter), 896 mUlp(ulp) {} 897 inline virtual void proc() const { 898 mAdapter.setUlpProxy(mUlp); 899 if (mUlp) { 900 mUlp->setCapabilities(ContextBase::getCarrierCapabilities()); 901 } 902 } 903 }; 904 905 sendMsg(new MsgSetUlpProxy(*this, ulp)); 906} 907 908void 909GnssAdapter::setUlpProxy(UlpProxyBase* ulp) 910{ 911 if (ulp == mUlpProxy) { 912 //This takes care of the case when double initalization happens 913 //and we get the same object back for UlpProxyBase . Do nothing 914 return; 915 } 916 917 LOC_LOGV("%s]: %p", __func__, ulp); 918 if (NULL == ulp) { 919 LOC_LOGE("%s]: ulp pointer is NULL", __func__); 920 ulp = new UlpProxyBase(); 921 } 922 923 if (LOC_POSITION_MODE_INVALID != mUlpProxy->mPosMode.mode) { 924 // need to send this mode and start msg to ULP 925 ulp->sendFixMode(mUlpProxy->mPosMode); 926 } 927 928 if (mUlpProxy->mFixSet) { 929 ulp->sendStartFix(); 930 } 931 932 delete mUlpProxy; 933 mUlpProxy = ulp; 934} 935 936void 937GnssAdapter::addClientCommand(LocationAPI* client, const LocationCallbacks& callbacks) 938{ 939 LOC_LOGD("%s]: client %p", __func__, client); 940 941 struct MsgAddClient : public LocMsg { 942 GnssAdapter& mAdapter; 943 LocationAPI* mClient; 944 const LocationCallbacks mCallbacks; 945 inline MsgAddClient(GnssAdapter& adapter, 946 LocationAPI* client, 947 const LocationCallbacks& callbacks) : 948 LocMsg(), 949 mAdapter(adapter), 950 mClient(client), 951 mCallbacks(callbacks) {} 952 inline virtual void proc() const { 953 mAdapter.saveClient(mClient, mCallbacks); 954 } 955 }; 956 957 sendMsg(new MsgAddClient(*this, client, callbacks)); 958} 959 960void 961GnssAdapter::removeClientCommand(LocationAPI* client) 962{ 963 LOC_LOGD("%s]: client %p", __func__, client); 964 965 struct MsgRemoveClient : public LocMsg { 966 GnssAdapter& mAdapter; 967 LocationAPI* mClient; 968 inline MsgRemoveClient(GnssAdapter& adapter, 969 LocationAPI* client) : 970 LocMsg(), 971 mAdapter(adapter), 972 mClient(client) {} 973 inline virtual void proc() const { 974 mAdapter.stopClientSessions(mClient); 975 mAdapter.eraseClient(mClient); 976 } 977 }; 978 979 sendMsg(new MsgRemoveClient(*this, client)); 980} 981 982void 983GnssAdapter::stopClientSessions(LocationAPI* client) 984{ 985 LOC_LOGD("%s]: client %p", __func__, client); 986 for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end();) { 987 if (client == it->first.client) { 988 LocationError err = stopTrackingMultiplex(it->first.client, it->first.id); 989 if (LOCATION_ERROR_SUCCESS == err) { 990 it = mTrackingSessions.erase(it); 991 continue; 992 } 993 } 994 ++it; // increment only when not erasing an iterator 995 } 996 997} 998 999void 1000GnssAdapter::updateClientsEventMask() 1001{ 1002 LOC_API_ADAPTER_EVENT_MASK_T mask = 0; 1003 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { 1004 if (it->second.trackingCb != nullptr) { 1005 mask |= LOC_API_ADAPTER_BIT_PARSED_POSITION_REPORT; 1006 } 1007 if (it->second.gnssNiCb != nullptr) { 1008 mask |= LOC_API_ADAPTER_BIT_NI_NOTIFY_VERIFY_REQUEST; 1009 } 1010 if (it->second.gnssSvCb != nullptr) { 1011 mask |= LOC_API_ADAPTER_BIT_SATELLITE_REPORT; 1012 } 1013 if (it->second.gnssNmeaCb != nullptr) { 1014 mask |= LOC_API_ADAPTER_BIT_NMEA_1HZ_REPORT; 1015 } 1016 if (it->second.gnssMeasurementsCb != nullptr) { 1017 mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT; 1018 } 1019 } 1020 1021 /* 1022 ** For Automotive use cases we need to enable MEASUREMENT and POLY 1023 ** when QDR is enabled 1024 */ 1025 if(1 == ContextBase::mGps_conf.EXTERNAL_DR_ENABLED) { 1026 mask |= LOC_API_ADAPTER_BIT_GNSS_MEASUREMENT; 1027 mask |= LOC_API_ADAPTER_BIT_GNSS_SV_POLYNOMIAL_REPORT; 1028 1029 LOC_LOGD("%s]: Auto usecase, Enable MEAS/POLY - mask 0x%x", __func__, mask); 1030 } 1031 1032 updateEvtMask(mask, LOC_REGISTRATION_MASK_SET); 1033} 1034 1035void 1036GnssAdapter::handleEngineUpEvent() 1037{ 1038 struct MsgRestartSessions : public LocMsg { 1039 GnssAdapter& mAdapter; 1040 inline MsgRestartSessions(GnssAdapter& adapter) : 1041 LocMsg(), 1042 mAdapter(adapter) {} 1043 virtual void proc() const { 1044 mAdapter.restartSessions(); 1045 } 1046 }; 1047 1048 setConfigCommand(); 1049 sendMsg(new MsgRestartSessions(*this)); 1050} 1051 1052void 1053GnssAdapter::restartSessions() 1054{ 1055 LOC_LOGD("%s]: ", __func__); 1056 1057 if (mTrackingSessions.empty()) { 1058 return; 1059 } 1060 1061 // get the LocationOptions that has the smallest interval, which should be the active one 1062 LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time 1063 for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) { 1064 if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet 1065 it->second.minInterval < smallestIntervalOptions.minInterval) { 1066 smallestIntervalOptions = it->second; 1067 } 1068 } 1069 1070 LocPosMode locPosMode = {}; 1071 convertOptions(locPosMode, smallestIntervalOptions); 1072 mLocApi->startFix(locPosMode); 1073} 1074 1075void 1076GnssAdapter::requestCapabilitiesCommand(LocationAPI* client) 1077{ 1078 LOC_LOGD("%s]: ", __func__); 1079 1080 struct MsgRequestCapabilities : public LocMsg { 1081 GnssAdapter& mAdapter; 1082 LocApiBase& mApi; 1083 LocationAPI* mClient; 1084 inline MsgRequestCapabilities(GnssAdapter& adapter, 1085 LocApiBase& api, 1086 LocationAPI* client) : 1087 LocMsg(), 1088 mAdapter(adapter), 1089 mApi(api), 1090 mClient(client) {} 1091 inline virtual void proc() const { 1092 LocationCallbacks callbacks = mAdapter.getClientCallbacks(mClient); 1093 if (callbacks.capabilitiesCb == nullptr) { 1094 LOC_LOGE("%s]: capabilitiesCb is NULL", __func__); 1095 return; 1096 } 1097 1098 LocationCapabilitiesMask mask = {}; 1099 // time based tracking always supported 1100 mask |= LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT; 1101 if (mApi.isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_LOCATION_BATCHING)){ 1102 mask |= LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT | 1103 LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT; 1104 } 1105 if (mApi.isMessageSupported(LOC_API_ADAPTER_MESSAGE_DISTANCE_BASE_TRACKING)) { 1106 mask |= LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT; 1107 } 1108 // geofence always supported 1109 mask |= LOCATION_CAPABILITIES_GEOFENCE_BIT; 1110 if (mApi.gnssConstellationConfig()) { 1111 mask |= LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT; 1112 } 1113 uint32_t carrierCapabilities = ContextBase::getCarrierCapabilities(); 1114 if (carrierCapabilities & LOC_GPS_CAPABILITY_MSB) { 1115 mask |= LOCATION_CAPABILITIES_GNSS_MSB_BIT; 1116 } 1117 if (LOC_GPS_CAPABILITY_MSA & carrierCapabilities) { 1118 mask |= LOCATION_CAPABILITIES_GNSS_MSA_BIT; 1119 } 1120 1121 callbacks.capabilitiesCb(mask); 1122 } 1123 }; 1124 1125 sendMsg(new MsgRequestCapabilities(*this, *mLocApi, client)); 1126} 1127 1128LocationCallbacks 1129GnssAdapter::getClientCallbacks(LocationAPI* client) 1130{ 1131 LocationCallbacks callbacks = {}; 1132 auto it = mClientData.find(client); 1133 if (it != mClientData.end()) { 1134 callbacks = it->second; 1135 } 1136 return callbacks; 1137} 1138 1139void 1140GnssAdapter::saveClient(LocationAPI* client, const LocationCallbacks& callbacks) 1141{ 1142 mClientData[client] = callbacks; 1143 updateClientsEventMask(); 1144} 1145 1146void 1147GnssAdapter::eraseClient(LocationAPI* client) 1148{ 1149 auto it = mClientData.find(client); 1150 if (it != mClientData.end()) { 1151 mClientData.erase(it); 1152 } 1153 updateClientsEventMask(); 1154} 1155 1156bool 1157GnssAdapter::hasTrackingCallback(LocationAPI* client) 1158{ 1159 auto it = mClientData.find(client); 1160 return (it != mClientData.end() && it->second.trackingCb); 1161} 1162 1163bool 1164GnssAdapter::hasMeasurementsCallback(LocationAPI* client) 1165{ 1166 auto it = mClientData.find(client); 1167 return (it != mClientData.end() && it->second.gnssMeasurementsCb); 1168} 1169 1170bool 1171GnssAdapter::isTrackingSession(LocationAPI* client, uint32_t sessionId) 1172{ 1173 LocationSessionKey key(client, sessionId); 1174 return (mTrackingSessions.find(key) != mTrackingSessions.end()); 1175} 1176 1177void 1178GnssAdapter::saveTrackingSession(LocationAPI* client, uint32_t sessionId, 1179 const LocationOptions& options) 1180{ 1181 LocationSessionKey key(client, sessionId); 1182 mTrackingSessions[key] = options; 1183} 1184 1185void 1186GnssAdapter::eraseTrackingSession(LocationAPI* client, uint32_t sessionId) 1187{ 1188 LocationSessionKey key(client, sessionId); 1189 auto it = mTrackingSessions.find(key); 1190 if (it != mTrackingSessions.end()) { 1191 mTrackingSessions.erase(it); 1192 } 1193 1194} 1195 1196void 1197GnssAdapter::reportResponse(LocationAPI* client, LocationError err, uint32_t sessionId) 1198{ 1199 LOC_LOGD("%s]: client %p id %u err %u", __func__, client, sessionId, err); 1200 1201 auto it = mClientData.find(client); 1202 if (it != mClientData.end() && 1203 it->second.responseCb != nullptr) { 1204 it->second.responseCb(err, sessionId); 1205 } else { 1206 LOC_LOGW("%s]: client %p id %u not found in data", __func__, client, sessionId); 1207 } 1208} 1209 1210void 1211GnssAdapter::reportResponse(LocationError err, uint32_t sessionId) 1212{ 1213 LOC_LOGD("%s]: id %u err %u", __func__, sessionId, err); 1214 1215 if (mControlCallbacks.size > 0 && mControlCallbacks.responseCb != nullptr) { 1216 mControlCallbacks.responseCb(err, sessionId); 1217 } else { 1218 LOC_LOGW("%s]: control client response callback not found", __func__); 1219 } 1220} 1221 1222void 1223GnssAdapter::reportResponse(size_t count, LocationError* errs, uint32_t* ids) 1224{ 1225 IF_LOC_LOGD { 1226 std::string idsString = "["; 1227 std::string errsString = "["; 1228 if (NULL != ids && NULL != errs) { 1229 for (size_t i=0; i < count; ++i) { 1230 idsString += std::to_string(ids[i]) + " "; 1231 errsString += std::to_string(errs[i]) + " "; 1232 } 1233 } 1234 idsString += "]"; 1235 errsString += "]"; 1236 1237 LOC_LOGD("%s]: ids %s errs %s", 1238 __func__, idsString.c_str(), errsString.c_str()); 1239 } 1240 1241 if (mControlCallbacks.size > 0 && mControlCallbacks.collectiveResponseCb != nullptr) { 1242 mControlCallbacks.collectiveResponseCb(count, errs, ids); 1243 } else { 1244 LOC_LOGW("%s]: control client callback not found", __func__); 1245 } 1246} 1247 1248uint32_t 1249GnssAdapter::startTrackingCommand(LocationAPI* client, LocationOptions& options) 1250{ 1251 uint32_t sessionId = generateSessionId(); 1252 LOC_LOGD("%s]: client %p id %u minInterval %u mode %u", 1253 __func__, client, sessionId, options.minInterval, options.mode); 1254 1255 struct MsgStartTracking : public LocMsg { 1256 GnssAdapter& mAdapter; 1257 LocApiBase& mApi; 1258 LocationAPI* mClient; 1259 uint32_t mSessionId; 1260 LocationOptions mOptions; 1261 inline MsgStartTracking(GnssAdapter& adapter, 1262 LocApiBase& api, 1263 LocationAPI* client, 1264 uint32_t sessionId, 1265 LocationOptions options) : 1266 LocMsg(), 1267 mAdapter(adapter), 1268 mApi(api), 1269 mClient(client), 1270 mSessionId(sessionId), 1271 mOptions(options) {} 1272 inline virtual void proc() const { 1273 LocationError err = LOCATION_ERROR_SUCCESS; 1274 if (!mAdapter.hasTrackingCallback(mClient) && 1275 !mAdapter.hasMeasurementsCallback(mClient)) { 1276 err = LOCATION_ERROR_CALLBACK_MISSING; 1277 } else if (0 == mOptions.size) { 1278 err = LOCATION_ERROR_INVALID_PARAMETER; 1279 } else { 1280 // Api doesn't support multiple clients for time based tracking, so mutiplex 1281 err = mAdapter.startTrackingMultiplex(mOptions); 1282 if (LOCATION_ERROR_SUCCESS == err) { 1283 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions); 1284 } 1285 } 1286 mAdapter.reportResponse(mClient, err, mSessionId); 1287 } 1288 }; 1289 1290 sendMsg(new MsgStartTracking(*this, *mLocApi, client, sessionId, options)); 1291 return sessionId; 1292 1293} 1294 1295LocationError 1296GnssAdapter::startTrackingMultiplex(const LocationOptions& options) 1297{ 1298 LocationError err = LOCATION_ERROR_SUCCESS; 1299 1300 if (mTrackingSessions.empty()) { 1301 err = startTracking(options); 1302 } else { 1303 // get the LocationOptions that has the smallest interval, which should be the active one 1304 LocationOptions smallestIntervalOptions = {}; // size is zero until set for the first time 1305 for (auto it = mTrackingSessions.begin(); it != mTrackingSessions.end(); ++it) { 1306 if (0 == smallestIntervalOptions.size || //size of zero means we havent set it yet 1307 it->second.minInterval < smallestIntervalOptions.minInterval) { 1308 smallestIntervalOptions = it->second; 1309 } 1310 } 1311 // if new session's minInterval is smaller than any in other sessions 1312 if (options.minInterval < smallestIntervalOptions.minInterval) { 1313 // restart time based tracking with new options 1314 err = startTracking(options); 1315 } 1316 } 1317 1318 return err; 1319} 1320 1321LocationError 1322GnssAdapter::startTracking(const LocationOptions& options) 1323{ 1324 LocationError err = LOCATION_ERROR_SUCCESS; 1325 LocPosMode locPosMode = {}; 1326 convertOptions(locPosMode, options); 1327 if (!mUlpProxy->sendFixMode(locPosMode)) { 1328 // do nothing 1329 } 1330 if (!mUlpProxy->sendStartFix()) { 1331 loc_api_adapter_err apiErr = mLocApi->startFix(locPosMode); 1332 if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) { 1333 err = LOCATION_ERROR_SUCCESS; 1334 } else { 1335 err = LOCATION_ERROR_GENERAL_FAILURE; 1336 } 1337 } 1338 1339 return err; 1340} 1341 1342void 1343GnssAdapter::setPositionModeCommand(LocPosMode& locPosMode) 1344{ 1345 LOC_LOGD("%s]: min_interval %u mode %u", 1346 __func__, locPosMode.min_interval, locPosMode.mode); 1347 1348 struct MsgSetPositionMode : public LocMsg { 1349 GnssAdapter& mAdapter; 1350 LocApiBase& mApi; 1351 LocPosMode mLocPosMode; 1352 inline MsgSetPositionMode(GnssAdapter& adapter, 1353 LocApiBase& api, 1354 LocPosMode& locPosMode) : 1355 LocMsg(), 1356 mAdapter(adapter), 1357 mApi(api), 1358 mLocPosMode(locPosMode) {} 1359 inline virtual void proc() const { 1360 // saves the mode in adapter to be used when startTrackingCommand is called from ULP 1361 mAdapter.setUlpPositionMode(mLocPosMode); 1362 mApi.setPositionMode(mLocPosMode); 1363 } 1364 }; 1365 1366 sendMsg(new MsgSetPositionMode(*this, *mLocApi, locPosMode)); 1367} 1368 1369void 1370GnssAdapter::startTrackingCommand() 1371{ 1372 LOC_LOGD("%s]: ", __func__); 1373 1374 struct MsgStartTracking : public LocMsg { 1375 GnssAdapter& mAdapter; 1376 LocApiBase& mApi; 1377 inline MsgStartTracking(GnssAdapter& adapter, 1378 LocApiBase& api) : 1379 LocMsg(), 1380 mAdapter(adapter), 1381 mApi(api) {} 1382 inline virtual void proc() const { 1383 // we get this call from ULP, so just call LocApi without multiplexing because 1384 // ulp would be doing the multiplexing for us if it is present 1385 LocPosMode& ulpPositionMode = mAdapter.getUlpPositionMode(); 1386 mApi.startFix(ulpPositionMode); 1387 } 1388 }; 1389 1390 sendMsg(new MsgStartTracking(*this, *mLocApi)); 1391} 1392 1393void 1394GnssAdapter::updateTrackingOptionsCommand(LocationAPI* client, uint32_t id, 1395 LocationOptions& options) 1396{ 1397 LOC_LOGD("%s]: client %p id %u minInterval %u mode %u", 1398 __func__, client, id, options.minInterval, options.mode); 1399 1400 struct MsgUpdateTracking : public LocMsg { 1401 GnssAdapter& mAdapter; 1402 LocApiBase& mApi; 1403 LocationAPI* mClient; 1404 uint32_t mSessionId; 1405 LocationOptions mOptions; 1406 inline MsgUpdateTracking(GnssAdapter& adapter, 1407 LocApiBase& api, 1408 LocationAPI* client, 1409 uint32_t sessionId, 1410 LocationOptions options) : 1411 LocMsg(), 1412 mAdapter(adapter), 1413 mApi(api), 1414 mClient(client), 1415 mSessionId(sessionId), 1416 mOptions(options) {} 1417 inline virtual void proc() const { 1418 if (mAdapter.isTrackingSession(mClient, mSessionId)) { 1419 LocationError err = LOCATION_ERROR_SUCCESS; 1420 if (0 == mOptions.size) { 1421 err = LOCATION_ERROR_INVALID_PARAMETER; 1422 } else { 1423 // Api doesn't support multiple clients for time based tracking, so mutiplex 1424 err = mAdapter.updateTrackingMultiplex(mClient, mSessionId, mOptions); 1425 if (LOCATION_ERROR_SUCCESS == err) { 1426 mAdapter.saveTrackingSession(mClient, mSessionId, mOptions); 1427 } 1428 } 1429 mAdapter.reportResponse(mClient, err, mSessionId); 1430 } 1431 // we do not reportResponse for the case where there is no existing tracking session 1432 // for the client and id being used, since updateTrackingCommand can be sent to both 1433 // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response 1434 } 1435 }; 1436 1437 sendMsg(new MsgUpdateTracking(*this, *mLocApi, client, id, options)); 1438} 1439 1440LocationError 1441GnssAdapter::updateTrackingMultiplex(LocationAPI* client, uint32_t id, 1442 const LocationOptions& options) 1443{ 1444 LocationError err = LOCATION_ERROR_SUCCESS; 1445 1446 if (1 == mTrackingSessions.size()) { 1447 err = startTracking(options); 1448 } else { 1449 LocationSessionKey key(client, id); 1450 1451 // get the session we are updating 1452 auto it = mTrackingSessions.find(key); 1453 if (it != mTrackingSessions.end()) { 1454 // find the smallest interval, other than the session we are updating 1455 LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time 1456 for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) { 1457 // if session is not the one we are updating and either smallest interval is not set 1458 // or there is a new smallest interval, then set the new smallest interval 1459 if (it2->first != key && (0 == smallestIntervalOptions.size || 1460 it2->second.minInterval < smallestIntervalOptions.minInterval)) { 1461 smallestIntervalOptions = it2->second; 1462 } 1463 } 1464 // if session we are updating has smaller interval then next smallest 1465 if (options.minInterval < smallestIntervalOptions.minInterval) { 1466 // restart time based tracking with the newly updated interval 1467 err = startTracking(options); 1468 // else if the session we are updating used to be the smallest 1469 } else if (it->second.minInterval < smallestIntervalOptions.minInterval) { 1470 // restart time based tracking with the next smallest 1471 err = startTracking(smallestIntervalOptions); 1472 } 1473 } 1474 } 1475 1476 return err; 1477} 1478 1479void 1480GnssAdapter::stopTrackingCommand(LocationAPI* client, uint32_t id) 1481{ 1482 LOC_LOGD("%s]: client %p id %u", __func__, client, id); 1483 1484 struct MsgStopTracking : public LocMsg { 1485 GnssAdapter& mAdapter; 1486 LocApiBase& mApi; 1487 LocationAPI* mClient; 1488 uint32_t mSessionId; 1489 inline MsgStopTracking(GnssAdapter& adapter, 1490 LocApiBase& api, 1491 LocationAPI* client, 1492 uint32_t sessionId) : 1493 LocMsg(), 1494 mAdapter(adapter), 1495 mApi(api), 1496 mClient(client), 1497 mSessionId(sessionId) {} 1498 inline virtual void proc() const { 1499 if (mAdapter.isTrackingSession(mClient, mSessionId)) { 1500 LocationError err = LOCATION_ERROR_SUCCESS; 1501 // Api doesn't support multiple clients for time based tracking, so mutiplex 1502 err = mAdapter.stopTrackingMultiplex(mClient, mSessionId); 1503 if (LOCATION_ERROR_SUCCESS == err) { 1504 mAdapter.eraseTrackingSession(mClient, mSessionId); 1505 } 1506 mAdapter.reportResponse(mClient, err, mSessionId); 1507 } 1508 // we do not reportResponse for the case where there is no existing tracking session 1509 // for the client and id being used, since stopTrackingCommand can be sent to both 1510 // GnssAdapter & FlpAdapter by LocationAPI and we want to avoid incorrect error response 1511 1512 } 1513 }; 1514 1515 sendMsg(new MsgStopTracking(*this, *mLocApi, client, id)); 1516} 1517 1518LocationError 1519GnssAdapter::stopTrackingMultiplex(LocationAPI* client, uint32_t id) 1520{ 1521 LocationError err = LOCATION_ERROR_SUCCESS; 1522 1523 if (1 == mTrackingSessions.size()) { 1524 err = stopTracking(); 1525 } else { 1526 LocationSessionKey key(client, id); 1527 1528 // get the session we are stopping 1529 auto it = mTrackingSessions.find(key); 1530 if (it != mTrackingSessions.end()) { 1531 // find the next smallest interval, other than the session we are stopping 1532 LocationOptions smallestIntervalOptions = {}; // size is 0 until set for the first time 1533 for (auto it2 = mTrackingSessions.begin(); it2 != mTrackingSessions.end(); ++it2) { 1534 // if session is not the one we are stopping and either smallest interval is not set 1535 // or there is a new smallest interval, then set the new smallest interval 1536 if (it2->first != key && (0 == smallestIntervalOptions.size || 1537 it2->second.minInterval < smallestIntervalOptions.minInterval)) { 1538 smallestIntervalOptions = it2->second; 1539 } 1540 } 1541 // if session we are stopping has smaller interval then next smallest 1542 if (it->second.minInterval < smallestIntervalOptions.minInterval) { 1543 // restart time based tracking with next smallest interval 1544 err = startTracking(smallestIntervalOptions); 1545 } 1546 } 1547 } 1548 1549 return err; 1550} 1551 1552LocationError 1553GnssAdapter::stopTracking() 1554{ 1555 LocationError err = LOCATION_ERROR_SUCCESS; 1556 if (!mUlpProxy->sendStopFix()) { 1557 loc_api_adapter_err apiErr = mLocApi->stopFix(); 1558 if (LOC_API_ADAPTER_ERR_SUCCESS == apiErr) { 1559 err = LOCATION_ERROR_SUCCESS; 1560 } else { 1561 err = LOCATION_ERROR_GENERAL_FAILURE; 1562 } 1563 } 1564 1565 return err; 1566} 1567 1568void 1569GnssAdapter::stopTrackingCommand() 1570{ 1571 LOC_LOGD("%s]: ", __func__); 1572 1573 struct MsgStopTracking : public LocMsg { 1574 GnssAdapter& mAdapter; 1575 LocApiBase& mApi; 1576 inline MsgStopTracking(GnssAdapter& adapter, 1577 LocApiBase& api) : 1578 LocMsg(), 1579 mAdapter(adapter), 1580 mApi(api) {} 1581 inline virtual void proc() const { 1582 // clear the position mode 1583 LocPosMode mLocPosMode = {}; 1584 mLocPosMode.mode = LOC_POSITION_MODE_INVALID; 1585 mAdapter.setUlpPositionMode(mLocPosMode); 1586 // don't need to multiplex because ULP will do that for us if it is present 1587 mApi.stopFix(); 1588 } 1589 }; 1590 1591 sendMsg(new MsgStopTracking(*this, *mLocApi)); 1592} 1593 1594void 1595GnssAdapter::getZppCommand() 1596{ 1597 LOC_LOGD("%s]: ", __func__); 1598 1599 struct MsgGetZpp : public LocMsg { 1600 GnssAdapter& mAdapter; 1601 LocApiBase& mApi; 1602 inline MsgGetZpp(GnssAdapter& adapter, 1603 LocApiBase& api) : 1604 LocMsg(), 1605 mAdapter(adapter), 1606 mApi(api) {} 1607 inline virtual void proc() const { 1608 UlpLocation location = {}; 1609 LocPosTechMask techMask = LOC_POS_TECH_MASK_DEFAULT; 1610 GpsLocationExtended locationExtended = {}; 1611 locationExtended.size = sizeof(locationExtended); 1612 1613 mApi.getBestAvailableZppFix(location.gpsLocation, techMask); 1614 //Mark the location source as from ZPP 1615 location.gpsLocation.flags |= LOCATION_HAS_SOURCE_INFO; 1616 location.position_source = ULP_LOCATION_IS_FROM_ZPP; 1617 1618 mAdapter.getUlpProxy()->reportPosition(location, 1619 locationExtended, 1620 LOC_SESS_SUCCESS, 1621 techMask); 1622 } 1623 }; 1624 1625 sendMsg(new MsgGetZpp(*this, *mLocApi)); 1626} 1627 1628bool 1629GnssAdapter::hasNiNotifyCallback(LocationAPI* client) 1630{ 1631 auto it = mClientData.find(client); 1632 return (it != mClientData.end() && it->second.gnssNiCb); 1633} 1634 1635void 1636GnssAdapter::gnssNiResponseCommand(LocationAPI* client, 1637 uint32_t id, 1638 GnssNiResponse response) 1639{ 1640 LOC_LOGD("%s]: client %p id %u response %u", __func__, client, id, response); 1641 1642 struct MsgGnssNiResponse : public LocMsg { 1643 GnssAdapter& mAdapter; 1644 LocationAPI* mClient; 1645 uint32_t mSessionId; 1646 GnssNiResponse mResponse; 1647 inline MsgGnssNiResponse(GnssAdapter& adapter, 1648 LocationAPI* client, 1649 uint32_t sessionId, 1650 GnssNiResponse response) : 1651 LocMsg(), 1652 mAdapter(adapter), 1653 mClient(client), 1654 mSessionId(sessionId), 1655 mResponse(response) {} 1656 inline virtual void proc() const { 1657 NiData& niData = mAdapter.getNiData(); 1658 LocationError err = LOCATION_ERROR_SUCCESS; 1659 if (!mAdapter.hasNiNotifyCallback(mClient)) { 1660 err = LOCATION_ERROR_ID_UNKNOWN; 1661 } else { 1662 NiSession* pSession = NULL; 1663 if (mSessionId == niData.sessionEs.reqID && 1664 NULL != niData.sessionEs.rawRequest) { 1665 pSession = &niData.sessionEs; 1666 // ignore any SUPL NI non-Es session if a SUPL NI ES is accepted 1667 if (mResponse == GNSS_NI_RESPONSE_ACCEPT && 1668 NULL != niData.session.rawRequest) { 1669 pthread_mutex_lock(&niData.session.tLock); 1670 niData.session.resp = GNSS_NI_RESPONSE_IGNORE; 1671 niData.session.respRecvd = true; 1672 pthread_cond_signal(&niData.session.tCond); 1673 pthread_mutex_unlock(&niData.session.tLock); 1674 } 1675 } else if (mSessionId == niData.session.reqID && 1676 NULL != niData.session.rawRequest) { 1677 pSession = &niData.session; 1678 } 1679 1680 if (pSession) { 1681 LOC_LOGI("%s]: gnssNiResponseCommand: send user mResponse %u for id %u", 1682 __func__, mResponse, mSessionId); 1683 pthread_mutex_lock(&pSession->tLock); 1684 pSession->resp = mResponse; 1685 pSession->respRecvd = true; 1686 pthread_cond_signal(&pSession->tCond); 1687 pthread_mutex_unlock(&pSession->tLock); 1688 } else { 1689 err = LOCATION_ERROR_ID_UNKNOWN; 1690 LOC_LOGE("%s]: gnssNiResponseCommand: id %u not an active session", 1691 __func__, mSessionId); 1692 } 1693 } 1694 mAdapter.reportResponse(mClient, err, mSessionId); 1695 } 1696 }; 1697 1698 sendMsg(new MsgGnssNiResponse(*this, client, id, response)); 1699 1700} 1701 1702void 1703GnssAdapter::gnssNiResponseCommand(GnssNiResponse response, void* rawRequest) 1704{ 1705 LOC_LOGD("%s]: response %u", __func__, response); 1706 1707 struct MsgGnssNiResponse : public LocMsg { 1708 LocApiBase& mApi; 1709 const GnssNiResponse mResponse; 1710 const void* mPayload; 1711 inline MsgGnssNiResponse(LocApiBase& api, 1712 const GnssNiResponse response, 1713 const void* rawRequest) : 1714 LocMsg(), 1715 mApi(api), 1716 mResponse(response), 1717 mPayload(rawRequest) {} 1718 inline virtual ~MsgGnssNiResponse() { 1719 // this is a bit weird since mPayload is not 1720 // allocated by this class. But there is no better way. 1721 // mPayload actually won't be NULL here. 1722 free((void*)mPayload); 1723 } 1724 inline virtual void proc() const { 1725 mApi.informNiResponse(mResponse, mPayload); 1726 } 1727 }; 1728 1729 sendMsg(new MsgGnssNiResponse(*mLocApi, response, rawRequest)); 1730 1731} 1732 1733uint32_t 1734GnssAdapter::enableCommand(LocationTechnologyType techType) 1735{ 1736 uint32_t sessionId = generateSessionId(); 1737 LOC_LOGD("%s]: id %u techType %u", __func__, sessionId, techType); 1738 1739 struct MsgEnableGnss : public LocMsg { 1740 GnssAdapter& mAdapter; 1741 LocApiBase& mApi; 1742 ContextBase& mContext; 1743 uint32_t mSessionId; 1744 LocationTechnologyType mTechType; 1745 inline MsgEnableGnss(GnssAdapter& adapter, 1746 LocApiBase& api, 1747 ContextBase& context, 1748 uint32_t sessionId, 1749 LocationTechnologyType techType) : 1750 LocMsg(), 1751 mAdapter(adapter), 1752 mApi(api), 1753 mContext(context), 1754 mSessionId(sessionId), 1755 mTechType(techType) {} 1756 inline virtual void proc() const { 1757 LocationError err = LOCATION_ERROR_SUCCESS; 1758 uint32_t powerVoteId = mAdapter.getPowerVoteId(); 1759 if (mTechType != LOCATION_TECHNOLOGY_TYPE_GNSS) { 1760 err = LOCATION_ERROR_INVALID_PARAMETER; 1761 } else if (powerVoteId > 0) { 1762 err = LOCATION_ERROR_ALREADY_STARTED; 1763 } else { 1764 mContext.modemPowerVote(true); 1765 mAdapter.setPowerVoteId(mSessionId); 1766 mApi.setGpsLock(GNSS_CONFIG_GPS_LOCK_NONE); 1767 } 1768 mAdapter.reportResponse(err, mSessionId); 1769 } 1770 }; 1771 1772 if (mContext != NULL) { 1773 sendMsg(new MsgEnableGnss(*this, *mLocApi, *mContext, sessionId, techType)); 1774 } else { 1775 LOC_LOGE("%s]: Context is NULL", __func__); 1776 } 1777 1778 return sessionId; 1779} 1780 1781void 1782GnssAdapter::disableCommand(uint32_t id) 1783{ 1784 LOC_LOGD("%s]: id %u", __func__, id); 1785 1786 struct MsgDisableGnss : public LocMsg { 1787 GnssAdapter& mAdapter; 1788 LocApiBase& mApi; 1789 ContextBase& mContext; 1790 uint32_t mSessionId; 1791 inline MsgDisableGnss(GnssAdapter& adapter, 1792 LocApiBase& api, 1793 ContextBase& context, 1794 uint32_t sessionId) : 1795 LocMsg(), 1796 mAdapter(adapter), 1797 mApi(api), 1798 mContext(context), 1799 mSessionId(sessionId) {} 1800 inline virtual void proc() const { 1801 LocationError err = LOCATION_ERROR_SUCCESS; 1802 uint32_t powerVoteId = mAdapter.getPowerVoteId(); 1803 if (powerVoteId != mSessionId) { 1804 err = LOCATION_ERROR_ID_UNKNOWN; 1805 } else { 1806 mContext.modemPowerVote(false); 1807 mAdapter.setPowerVoteId(0); 1808 mApi.setGpsLock(mAdapter.convertGpsLock(ContextBase::mGps_conf.GPS_LOCK)); 1809 } 1810 mAdapter.reportResponse(err, mSessionId); 1811 } 1812 }; 1813 1814 if (mContext != NULL) { 1815 sendMsg(new MsgDisableGnss(*this, *mLocApi, *mContext, id)); 1816 } 1817 1818} 1819 1820void 1821GnssAdapter::reportPositionEvent(const UlpLocation& ulpLocation, 1822 const GpsLocationExtended& locationExtended, 1823 enum loc_sess_status status, 1824 LocPosTechMask techMask, 1825 bool fromUlp) 1826{ 1827 LOC_LOGD("%s]: fromUlp %u status %u", __func__, fromUlp, status); 1828 1829 // if this event is not called from ULP, then try to call into ULP and return if successfull 1830 if (!fromUlp) { 1831 if (mUlpProxy->reportPosition(ulpLocation, locationExtended, 1832 status, techMask)) { 1833 return; 1834 } 1835 } 1836 1837 struct MsgReportPosition : public LocMsg { 1838 GnssAdapter& mAdapter; 1839 const UlpLocation mUlpLocation; 1840 const GpsLocationExtended mLocationExtended; 1841 loc_sess_status mStatus; 1842 LocPosTechMask mTechMask; 1843 inline MsgReportPosition(GnssAdapter& adapter, 1844 const UlpLocation& ulpLocation, 1845 const GpsLocationExtended& locationExtended, 1846 loc_sess_status status, 1847 LocPosTechMask techMask) : 1848 LocMsg(), 1849 mAdapter(adapter), 1850 mUlpLocation(ulpLocation), 1851 mLocationExtended(locationExtended), 1852 mStatus(status), 1853 mTechMask(techMask) {} 1854 inline virtual void proc() const { 1855 // extract bug report info - this returns true if consumed by systemstatus 1856 SystemStatus* s = LocDualContext::getSystemStatus(); 1857 if ((nullptr != s) && (LOC_SESS_SUCCESS == mStatus)){ 1858 s->eventPosition(mUlpLocation, mLocationExtended); 1859 } 1860 mAdapter.reportPosition(mUlpLocation, mLocationExtended, mStatus, mTechMask); 1861 } 1862 }; 1863 1864 sendMsg(new MsgReportPosition(*this, ulpLocation, locationExtended, status, techMask)); 1865} 1866 1867void 1868GnssAdapter::reportPosition(const UlpLocation& ulpLocation, 1869 const GpsLocationExtended& locationExtended, 1870 enum loc_sess_status status, 1871 LocPosTechMask techMask) 1872{ 1873 bool reported = false; 1874 if (LOC_SESS_FAILURE == status) { 1875 Location invalidLocation = {}; 1876 invalidLocation.size = sizeof(Location); 1877 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { 1878 if (nullptr != it->second.trackingCb) { 1879 it->second.trackingCb(invalidLocation); 1880 } 1881 } 1882 reported = true; 1883 } 1884 // what's in the else if is... (line by line) 1885 // 1. this is a final fix; and 1886 // 1.1 it is a Satellite fix; or 1887 // 1.2 it is a sensor fix 1888 // 2. (must be intermediate fix... implicit) 1889 // 2.1 we accepte intermediate; and 1890 // 2.2 it is NOT the case that 1891 // 2.2.1 there is inaccuracy; and 1892 // 2.2.2 we care about inaccuracy; and 1893 // 2.2.3 the inaccuracy exceeds our tolerance 1894 else if ((LOC_SESS_SUCCESS == status && 1895 ((LOC_POS_TECH_MASK_SATELLITE | 1896 LOC_POS_TECH_MASK_SENSORS | 1897 LOC_POS_TECH_MASK_HYBRID) & 1898 techMask)) || 1899 (LOC_SESS_INTERMEDIATE == ContextBase::mGps_conf.INTERMEDIATE_POS && 1900 !((ulpLocation.gpsLocation.flags & 1901 LOC_GPS_LOCATION_HAS_ACCURACY) && 1902 (ContextBase::mGps_conf.ACCURACY_THRES != 0) && 1903 (ulpLocation.gpsLocation.accuracy > 1904 ContextBase::mGps_conf.ACCURACY_THRES)))) { 1905 if (locationExtended.flags & GPS_LOCATION_EXTENDED_HAS_GNSS_SV_USED_DATA) { 1906 mGnssSvIdUsedInPosAvail = true; 1907 mGnssSvIdUsedInPosition = locationExtended.gnss_sv_used_ids; 1908 } 1909 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { 1910 if (nullptr != it->second.trackingCb) { 1911 Location location = {}; 1912 convertLocation(location, ulpLocation.gpsLocation, locationExtended, techMask); 1913 it->second.trackingCb(location); 1914 } 1915 if (nullptr != it->second.gnssLocationInfoCb) { 1916 GnssLocationInfoNotification locationInfo = {}; 1917 convertLocationInfo(locationInfo, locationExtended); 1918 it->second.gnssLocationInfoCb(locationInfo); 1919 } 1920 } 1921 reported = true; 1922 } 1923 1924 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) { 1925 uint8_t generate_nmea = (reported && status != LOC_SESS_FAILURE); 1926 std::vector<std::string> nmeaArraystr; 1927 loc_nmea_generate_pos(ulpLocation, locationExtended, generate_nmea, nmeaArraystr); 1928 for (auto sentence : nmeaArraystr) { 1929 reportNmea(sentence.c_str(), sentence.length()); 1930 } 1931 } 1932 1933 // Free the allocated memory for rawData 1934 UlpLocation* gp = (UlpLocation*)&(ulpLocation); 1935 if (gp != NULL && gp->rawData != NULL) 1936 { 1937 delete (char*)gp->rawData; 1938 gp->rawData = NULL; 1939 gp->rawDataSize = 0; 1940 } 1941} 1942 1943void 1944GnssAdapter::reportSvEvent(const GnssSvNotification& svNotify, 1945 bool fromUlp) 1946{ 1947 LOC_LOGD("%s]: fromUlp %u", __func__, fromUlp); 1948 1949 // if this event is not called from ULP, then try to call into ULP and return if successfull 1950 if (!fromUlp) { 1951 if (mUlpProxy->reportSv(svNotify)) { 1952 return; 1953 } 1954 } 1955 1956 struct MsgReportSv : public LocMsg { 1957 GnssAdapter& mAdapter; 1958 const GnssSvNotification mSvNotify; 1959 inline MsgReportSv(GnssAdapter& adapter, 1960 const GnssSvNotification& svNotify) : 1961 LocMsg(), 1962 mAdapter(adapter), 1963 mSvNotify(svNotify) {} 1964 inline virtual void proc() const { 1965 mAdapter.reportSv((GnssSvNotification&)mSvNotify); 1966 } 1967 }; 1968 1969 sendMsg(new MsgReportSv(*this, svNotify)); 1970} 1971 1972void 1973GnssAdapter::reportSv(GnssSvNotification& svNotify) 1974{ 1975 if (mGnssSvIdUsedInPosAvail) { 1976 int numSv = svNotify.count; 1977 int16_t gnssSvId = 0; 1978 uint64_t svUsedIdMask = 0; 1979 for (int i=0; i < numSv; i++) { 1980 gnssSvId = svNotify.gnssSvs[i].svId; 1981 switch (svNotify.gnssSvs[i].type) { 1982 case GNSS_SV_TYPE_GPS: 1983 svUsedIdMask = mGnssSvIdUsedInPosition.gps_sv_used_ids_mask; 1984 break; 1985 case GNSS_SV_TYPE_GLONASS: 1986 svUsedIdMask = mGnssSvIdUsedInPosition.glo_sv_used_ids_mask; 1987 break; 1988 case GNSS_SV_TYPE_BEIDOU: 1989 svUsedIdMask = mGnssSvIdUsedInPosition.bds_sv_used_ids_mask; 1990 break; 1991 case GNSS_SV_TYPE_GALILEO: 1992 svUsedIdMask = mGnssSvIdUsedInPosition.gal_sv_used_ids_mask; 1993 break; 1994 case GNSS_SV_TYPE_QZSS: 1995 svUsedIdMask = mGnssSvIdUsedInPosition.qzss_sv_used_ids_mask; 1996 break; 1997 default: 1998 svUsedIdMask = 0; 1999 break; 2000 } 2001 2002 // If SV ID was used in previous position fix, then set USED_IN_FIX 2003 // flag, else clear the USED_IN_FIX flag. 2004 if (svUsedIdMask & (1 << (gnssSvId - 1))) { 2005 svNotify.gnssSvs[i].gnssSvOptionsMask |= GNSS_SV_OPTIONS_USED_IN_FIX_BIT; 2006 } 2007 } 2008 } 2009 2010 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { 2011 if (nullptr != it->second.gnssSvCb) { 2012 it->second.gnssSvCb(svNotify); 2013 } 2014 } 2015 2016 if (NMEA_PROVIDER_AP == ContextBase::mGps_conf.NMEA_PROVIDER && !mTrackingSessions.empty()) { 2017 std::vector<std::string> nmeaArraystr; 2018 loc_nmea_generate_sv(svNotify, nmeaArraystr); 2019 for (auto sentence : nmeaArraystr) { 2020 reportNmea(sentence.c_str(), sentence.length()); 2021 } 2022 } 2023 2024 mGnssSvIdUsedInPosAvail = false; 2025} 2026 2027void 2028GnssAdapter::reportNmeaEvent(const char* nmea, size_t length, bool fromUlp) 2029{ 2030 // if this event is not called from ULP, then try to call into ULP and return if successfull 2031 if (!fromUlp && !loc_nmea_is_debug(nmea, length)) { 2032 if (mUlpProxy->reportNmea(nmea, length)) { 2033 return; 2034 } 2035 } 2036 2037 struct MsgReportNmea : public LocMsg { 2038 GnssAdapter& mAdapter; 2039 const char* mNmea; 2040 size_t mLength; 2041 inline MsgReportNmea(GnssAdapter& adapter, 2042 const char* nmea, 2043 size_t length) : 2044 LocMsg(), 2045 mAdapter(adapter), 2046 mNmea(new char[length+1]), 2047 mLength(length) { 2048 strlcpy((char*)mNmea, nmea, length+1); 2049 } 2050 inline virtual ~MsgReportNmea() 2051 { 2052 delete[] mNmea; 2053 } 2054 inline virtual void proc() const { 2055 // extract bug report info - this returns true if consumed by systemstatus 2056 bool ret = false; 2057 SystemStatus* s = LocDualContext::getSystemStatus(); 2058 if (nullptr != s) { 2059 ret = s->setNmeaString(mNmea, mLength); 2060 } 2061 if (false == ret) { 2062 // forward NMEA message to upper layer 2063 mAdapter.reportNmea(mNmea, mLength); 2064 } 2065 } 2066 }; 2067 2068 sendMsg(new MsgReportNmea(*this, nmea, length)); 2069} 2070 2071void 2072GnssAdapter::reportNmea(const char* nmea, size_t length) 2073{ 2074 GnssNmeaNotification nmeaNotification = {}; 2075 nmeaNotification.size = sizeof(GnssNmeaNotification); 2076 2077 struct timeval tv; 2078 gettimeofday(&tv, (struct timezone *) NULL); 2079 int64_t now = tv.tv_sec * 1000LL + tv.tv_usec / 1000; 2080 nmeaNotification.timestamp = now; 2081 nmeaNotification.nmea = nmea; 2082 nmeaNotification.length = length; 2083 2084 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { 2085 if (nullptr != it->second.gnssNmeaCb) { 2086 it->second.gnssNmeaCb(nmeaNotification); 2087 } 2088 } 2089} 2090 2091bool 2092GnssAdapter::requestNiNotifyEvent(const GnssNiNotification ¬ify, const void* data) 2093{ 2094 LOC_LOGI("%s]: notif_type: %d, timeout: %d, default_resp: %d" 2095 "requestor_id: %s (encoding: %d) text: %s text (encoding: %d) extras: %s", 2096 __func__, notify.type, notify.timeout, notify.timeoutResponse, 2097 notify.requestor, notify.requestorEncoding, 2098 notify.message, notify.messageEncoding, notify.extras); 2099 2100 struct MsgReportNiNotify : public LocMsg { 2101 GnssAdapter& mAdapter; 2102 const GnssNiNotification mNotify; 2103 const void* mData; 2104 inline MsgReportNiNotify(GnssAdapter& adapter, 2105 const GnssNiNotification& notify, 2106 const void* data) : 2107 LocMsg(), 2108 mAdapter(adapter), 2109 mNotify(notify), 2110 mData(data) {} 2111 inline virtual void proc() const { 2112 mAdapter.requestNiNotify(mNotify, mData); 2113 } 2114 }; 2115 2116 sendMsg(new MsgReportNiNotify(*this, notify, data)); 2117 2118 return true; 2119} 2120 2121static void* niThreadProc(void *args) 2122{ 2123 NiSession* pSession = (NiSession*)args; 2124 int rc = 0; /* return code from pthread calls */ 2125 2126 struct timeval present_time; 2127 struct timespec expire_time; 2128 2129 pthread_mutex_lock(&pSession->tLock); 2130 /* Calculate absolute expire time */ 2131 gettimeofday(&present_time, NULL); 2132 expire_time.tv_sec = present_time.tv_sec + pSession->respTimeLeft; 2133 expire_time.tv_nsec = present_time.tv_usec * 1000; 2134 LOC_LOGD("%s]: time out set for abs time %ld with delay %d sec", 2135 __func__, (long)expire_time.tv_sec, pSession->respTimeLeft); 2136 2137 while (!pSession->respRecvd) { 2138 rc = pthread_cond_timedwait(&pSession->tCond, 2139 &pSession->tLock, 2140 &expire_time); 2141 if (rc == ETIMEDOUT) { 2142 pSession->resp = GNSS_NI_RESPONSE_NO_RESPONSE; 2143 LOC_LOGD("%s]: time out after valting for specified time. Ret Val %d", 2144 __func__, rc); 2145 break; 2146 } 2147 } 2148 LOC_LOGD("%s]: Java layer has sent us a user response and return value from " 2149 "pthread_cond_timedwait = %d pSession->resp is %u", __func__, rc, pSession->resp); 2150 pSession->respRecvd = false; /* Reset the user response flag for the next session*/ 2151 2152 // adding this check to support modem restart, in which case, we need the thread 2153 // to exit without calling sending data. We made sure that rawRequest is NULL in 2154 // loc_eng_ni_reset_on_engine_restart() 2155 GnssAdapter* adapter = pSession->adapter; 2156 GnssNiResponse resp; 2157 void* rawRequest = NULL; 2158 bool sendResponse = false; 2159 2160 if (NULL != pSession->rawRequest) { 2161 if (pSession->resp != GNSS_NI_RESPONSE_IGNORE) { 2162 resp = pSession->resp; 2163 rawRequest = pSession->rawRequest; 2164 sendResponse = true; 2165 } else { 2166 free(pSession->rawRequest); 2167 } 2168 pSession->rawRequest = NULL; 2169 } 2170 pthread_mutex_unlock(&pSession->tLock); 2171 2172 pSession->respTimeLeft = 0; 2173 pSession->reqID = 0; 2174 2175 if (sendResponse) { 2176 adapter->gnssNiResponseCommand(resp, rawRequest); 2177 } 2178 2179 return NULL; 2180} 2181 2182bool 2183GnssAdapter::requestNiNotify(const GnssNiNotification& notify, const void* data) 2184{ 2185 NiSession* pSession = NULL; 2186 gnssNiCallback gnssNiCb = nullptr; 2187 2188 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { 2189 if (nullptr != it->second.gnssNiCb) { 2190 gnssNiCb = it->second.gnssNiCb; 2191 break; 2192 } 2193 } 2194 if (nullptr == gnssNiCb) { 2195 EXIT_LOG(%s, "no clients with gnssNiCb."); 2196 return false; 2197 } 2198 2199 if (notify.type == GNSS_NI_TYPE_EMERGENCY_SUPL) { 2200 if (NULL != mNiData.sessionEs.rawRequest) { 2201 LOC_LOGI("%s]: supl es NI in progress, new supl es NI ignored, type: %d", 2202 __func__, notify.type); 2203 if (NULL != data) { 2204 free((void*)data); 2205 } 2206 } else { 2207 pSession = &mNiData.sessionEs; 2208 } 2209 } else { 2210 if (NULL != mNiData.session.rawRequest || 2211 NULL != mNiData.sessionEs.rawRequest) { 2212 LOC_LOGI("%s]: supl NI in progress, new supl NI ignored, type: %d", 2213 __func__, notify.type); 2214 if (NULL != data) { 2215 free((void*)data); 2216 } 2217 } else { 2218 pSession = &mNiData.session; 2219 } 2220 } 2221 2222 if (pSession) { 2223 /* Save request */ 2224 pSession->rawRequest = (void*)data; 2225 pSession->reqID = ++mNiData.reqIDCounter; 2226 pSession->adapter = this; 2227 2228 int sessionId = pSession->reqID; 2229 2230 /* For robustness, spawn a thread at this point to timeout to clear up the notification 2231 * status, even though the OEM layer in java does not do so. 2232 **/ 2233 pSession->respTimeLeft = 2234 5 + (notify.timeout != 0 ? notify.timeout : LOC_NI_NO_RESPONSE_TIME); 2235 2236 int rc = 0; 2237 rc = pthread_create(&pSession->thread, NULL, niThreadProc, pSession); 2238 if (rc) { 2239 LOC_LOGE("%s]: Loc NI thread is not created.", __func__); 2240 } 2241 rc = pthread_detach(pSession->thread); 2242 if (rc) { 2243 LOC_LOGE("%s]: Loc NI thread is not detached.", __func__); 2244 } 2245 2246 if (nullptr != gnssNiCb) { 2247 gnssNiCb(sessionId, notify); 2248 } 2249 } 2250 2251 return true; 2252} 2253 2254void 2255GnssAdapter::reportGnssMeasurementDataEvent(const GnssMeasurementsNotification& measurementsNotify) 2256{ 2257 LOC_LOGD("%s]: ", __func__); 2258 2259 struct MsgReportGnssMeasurementData : public LocMsg { 2260 GnssAdapter& mAdapter; 2261 const GnssMeasurementsNotification mMeasurementsNotify; 2262 inline MsgReportGnssMeasurementData(GnssAdapter& adapter, 2263 const GnssMeasurementsNotification& measurementsNotify) : 2264 LocMsg(), 2265 mAdapter(adapter), 2266 mMeasurementsNotify(measurementsNotify) {} 2267 inline virtual void proc() const { 2268 mAdapter.reportGnssMeasurementData(mMeasurementsNotify); 2269 } 2270 }; 2271 2272 sendMsg(new MsgReportGnssMeasurementData(*this, measurementsNotify)); 2273} 2274 2275void 2276GnssAdapter::reportGnssMeasurementData(const GnssMeasurementsNotification& measurementsNotify) 2277{ 2278 for (auto it=mClientData.begin(); it != mClientData.end(); ++it) { 2279 if (nullptr != it->second.gnssMeasurementsCb) { 2280 it->second.gnssMeasurementsCb(measurementsNotify); 2281 } 2282 } 2283} 2284 2285void 2286GnssAdapter::reportSvMeasurementEvent(GnssSvMeasurementSet &svMeasurementSet) 2287{ 2288 LOC_LOGD("%s]: ", __func__); 2289 2290 // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary. 2291 mUlpProxy->reportSvMeasurement(svMeasurementSet); 2292} 2293 2294void 2295GnssAdapter::reportSvPolynomialEvent(GnssSvPolynomial &svPolynomial) 2296{ 2297 LOC_LOGD("%s]: ", __func__); 2298 2299 // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary. 2300 mUlpProxy->reportSvPolynomial(svPolynomial); 2301} 2302 2303/* INIT LOC AGPS MANAGER */ 2304void GnssAdapter::initAgpsCommand(void* statusV4Cb){ 2305 2306 LOC_LOGI("GnssAdapter::initAgpsCommand"); 2307 2308 /* Set ATL open/close callbacks */ 2309 AgpsAtlOpenStatusCb atlOpenStatusCb = 2310 [this](int handle, int isSuccess, char* apn, 2311 AGpsBearerType bearerType, AGpsExtType agpsType) { 2312 2313 mLocApi->atlOpenStatus( 2314 handle, isSuccess, apn, bearerType, agpsType); 2315 }; 2316 AgpsAtlCloseStatusCb atlCloseStatusCb = 2317 [this](int handle, int isSuccess) { 2318 2319 mLocApi->atlCloseStatus(handle, isSuccess); 2320 }; 2321 2322 /* Register DS Client APIs */ 2323 AgpsDSClientInitFn dsClientInitFn = 2324 [this](bool isDueToSSR) { 2325 2326 return mLocApi->initDataServiceClient(isDueToSSR); 2327 }; 2328 2329 AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn = 2330 [this] { 2331 2332 return mLocApi->openAndStartDataCall(); 2333 }; 2334 2335 AgpsDSClientStopDataCallFn dsClientStopDataCallFn = 2336 [this] { 2337 2338 mLocApi->stopDataCall(); 2339 }; 2340 2341 AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn = 2342 [this] { 2343 2344 mLocApi->closeDataCall(); 2345 }; 2346 2347 AgpsDSClientReleaseFn dsClientReleaseFn = 2348 [this] { 2349 2350 mLocApi->releaseDataServiceClient(); 2351 }; 2352 2353 /* Send Msg function */ 2354 SendMsgToAdapterMsgQueueFn sendMsgFn = 2355 [this](LocMsg* msg) { 2356 2357 sendMsg(msg); 2358 }; 2359 2360 /* Message to initialize AGPS module */ 2361 struct AgpsMsgInit: public LocMsg { 2362 2363 AgpsManager* mAgpsManager; 2364 2365 AgpsFrameworkInterface::AgnssStatusIpV4Cb mFrameworkStatusV4Cb; 2366 2367 AgpsAtlOpenStatusCb mAtlOpenStatusCb; 2368 AgpsAtlCloseStatusCb mAtlCloseStatusCb; 2369 2370 AgpsDSClientInitFn mDSClientInitFn; 2371 AgpsDSClientOpenAndStartDataCallFn mDSClientOpenAndStartDataCallFn; 2372 AgpsDSClientStopDataCallFn mDSClientStopDataCallFn; 2373 AgpsDSClientCloseDataCallFn mDSClientCloseDataCallFn; 2374 AgpsDSClientReleaseFn mDSClientReleaseFn; 2375 2376 SendMsgToAdapterMsgQueueFn mSendMsgFn; 2377 GnssAdapter& mAdapter; 2378 2379 inline AgpsMsgInit(AgpsManager* agpsManager, 2380 AgpsFrameworkInterface::AgnssStatusIpV4Cb frameworkStatusV4Cb, 2381 AgpsAtlOpenStatusCb atlOpenStatusCb, 2382 AgpsAtlCloseStatusCb atlCloseStatusCb, 2383 AgpsDSClientInitFn dsClientInitFn, 2384 AgpsDSClientOpenAndStartDataCallFn dsClientOpenAndStartDataCallFn, 2385 AgpsDSClientStopDataCallFn dsClientStopDataCallFn, 2386 AgpsDSClientCloseDataCallFn dsClientCloseDataCallFn, 2387 AgpsDSClientReleaseFn dsClientReleaseFn, 2388 SendMsgToAdapterMsgQueueFn sendMsgFn, 2389 GnssAdapter& adapter) : 2390 LocMsg(), mAgpsManager(agpsManager), mFrameworkStatusV4Cb( 2391 frameworkStatusV4Cb), mAtlOpenStatusCb(atlOpenStatusCb), mAtlCloseStatusCb( 2392 atlCloseStatusCb), mDSClientInitFn(dsClientInitFn), mDSClientOpenAndStartDataCallFn( 2393 dsClientOpenAndStartDataCallFn), mDSClientStopDataCallFn( 2394 dsClientStopDataCallFn), mDSClientCloseDataCallFn( 2395 dsClientCloseDataCallFn), mDSClientReleaseFn( 2396 dsClientReleaseFn), mSendMsgFn(sendMsgFn), 2397 mAdapter(adapter) { 2398 2399 LOC_LOGV("AgpsMsgInit"); 2400 } 2401 2402 inline virtual void proc() const { 2403 2404 LOC_LOGV("AgpsMsgInit::proc()"); 2405 2406 mAgpsManager->registerCallbacks(mFrameworkStatusV4Cb, mAtlOpenStatusCb, 2407 mAtlCloseStatusCb, mDSClientInitFn, 2408 mDSClientOpenAndStartDataCallFn, mDSClientStopDataCallFn, 2409 mDSClientCloseDataCallFn, mDSClientReleaseFn, mSendMsgFn); 2410 2411 mAgpsManager->createAgpsStateMachines(); 2412 2413 /* Register for AGPS event mask */ 2414 mAdapter.updateEvtMask(LOC_API_ADAPTER_BIT_LOCATION_SERVER_REQUEST, 2415 LOC_REGISTRATION_MASK_ENABLED); 2416 } 2417 }; 2418 2419 /* Send message to initialize AGPS Manager */ 2420 sendMsg(new AgpsMsgInit( 2421 &mAgpsManager, 2422 (AgpsFrameworkInterface::AgnssStatusIpV4Cb)statusV4Cb, 2423 atlOpenStatusCb, atlCloseStatusCb, 2424 dsClientInitFn, dsClientOpenAndStartDataCallFn, 2425 dsClientStopDataCallFn, dsClientCloseDataCallFn, 2426 dsClientReleaseFn, 2427 sendMsgFn, 2428 *this)); 2429} 2430 2431/* GnssAdapter::requestATL 2432 * Method triggered in QMI thread as part of handling below message: 2433 * eQMI_LOC_SERVER_REQUEST_OPEN_V02 2434 * Triggers the AGPS state machine to setup AGPS call for below WWAN types: 2435 * eQMI_LOC_WWAN_TYPE_INTERNET_V02 2436 * eQMI_LOC_WWAN_TYPE_AGNSS_V02 */ 2437bool GnssAdapter::requestATL(int connHandle, LocAGpsType agpsType){ 2438 2439 LOC_LOGI("GnssAdapter::requestATL"); 2440 2441 sendMsg( new AgpsMsgRequestATL( 2442 &mAgpsManager, connHandle, (AGpsExtType)agpsType)); 2443 2444 return true; 2445} 2446 2447/* GnssAdapter::requestSuplES 2448 * Method triggered in QMI thread as part of handling below message: 2449 * eQMI_LOC_SERVER_REQUEST_OPEN_V02 2450 * Triggers the AGPS state machine to setup AGPS call for below WWAN types: 2451 * eQMI_LOC_WWAN_TYPE_AGNSS_EMERGENCY_V02 */ 2452bool GnssAdapter::requestSuplES(int connHandle){ 2453 2454 LOC_LOGI("GnssAdapter::requestSuplES"); 2455 2456 sendMsg( new AgpsMsgRequestATL( 2457 &mAgpsManager, connHandle, LOC_AGPS_TYPE_SUPL_ES)); 2458 2459 return true; 2460} 2461 2462/* GnssAdapter::releaseATL 2463 * Method triggered in QMI thread as part of handling below message: 2464 * eQMI_LOC_SERVER_REQUEST_CLOSE_V02 2465 * Triggers teardown of an existing AGPS call */ 2466bool GnssAdapter::releaseATL(int connHandle){ 2467 2468 LOC_LOGI("GnssAdapter::releaseATL"); 2469 2470 /* Release SUPL/INTERNET/SUPL_ES ATL */ 2471 struct AgpsMsgReleaseATL: public LocMsg { 2472 2473 AgpsManager* mAgpsManager; 2474 int mConnHandle; 2475 2476 inline AgpsMsgReleaseATL(AgpsManager* agpsManager, int connHandle) : 2477 LocMsg(), mAgpsManager(agpsManager), mConnHandle(connHandle) { 2478 2479 LOC_LOGV("AgpsMsgReleaseATL"); 2480 } 2481 2482 inline virtual void proc() const { 2483 2484 LOC_LOGV("AgpsMsgReleaseATL::proc()"); 2485 mAgpsManager->releaseATL(mConnHandle); 2486 } 2487 }; 2488 2489 sendMsg( new AgpsMsgReleaseATL(&mAgpsManager, connHandle)); 2490 2491 return true; 2492} 2493 2494/* GnssAdapter::reportDataCallOpened 2495 * DS Client data call opened successfully. 2496 * Send message to AGPS Manager to handle. */ 2497bool GnssAdapter::reportDataCallOpened(){ 2498 2499 LOC_LOGI("GnssAdapter::reportDataCallOpened"); 2500 2501 struct AgpsMsgSuplEsOpened: public LocMsg { 2502 2503 AgpsManager* mAgpsManager; 2504 2505 inline AgpsMsgSuplEsOpened(AgpsManager* agpsManager) : 2506 LocMsg(), mAgpsManager(agpsManager) { 2507 2508 LOC_LOGV("AgpsMsgSuplEsOpened"); 2509 } 2510 2511 inline virtual void proc() const { 2512 2513 LOC_LOGV("AgpsMsgSuplEsOpened::proc()"); 2514 mAgpsManager->reportDataCallOpened(); 2515 } 2516 }; 2517 2518 sendMsg( new AgpsMsgSuplEsOpened(&mAgpsManager)); 2519 2520 return true; 2521} 2522 2523/* GnssAdapter::reportDataCallClosed 2524 * DS Client data call closed. 2525 * Send message to AGPS Manager to handle. */ 2526bool GnssAdapter::reportDataCallClosed(){ 2527 2528 LOC_LOGI("GnssAdapter::reportDataCallClosed"); 2529 2530 struct AgpsMsgSuplEsClosed: public LocMsg { 2531 2532 AgpsManager* mAgpsManager; 2533 2534 inline AgpsMsgSuplEsClosed(AgpsManager* agpsManager) : 2535 LocMsg(), mAgpsManager(agpsManager) { 2536 2537 LOC_LOGV("AgpsMsgSuplEsClosed"); 2538 } 2539 2540 inline virtual void proc() const { 2541 2542 LOC_LOGV("AgpsMsgSuplEsClosed::proc()"); 2543 mAgpsManager->reportDataCallClosed(); 2544 } 2545 }; 2546 2547 sendMsg( new AgpsMsgSuplEsClosed(&mAgpsManager)); 2548 2549 return true; 2550} 2551 2552void GnssAdapter::dataConnOpenCommand( 2553 AGpsExtType agpsType, 2554 const char* apnName, int apnLen, LocApnIpType ipType){ 2555 2556 LOC_LOGI("GnssAdapter::frameworkDataConnOpen"); 2557 2558 struct AgpsMsgAtlOpenSuccess: public LocMsg { 2559 2560 AgpsManager* mAgpsManager; 2561 AGpsExtType mAgpsType; 2562 char* mApnName; 2563 int mApnLen; 2564 LocApnIpType mIpType; 2565 2566 inline AgpsMsgAtlOpenSuccess(AgpsManager* agpsManager, AGpsExtType agpsType, 2567 const char* apnName, int apnLen, LocApnIpType ipType) : 2568 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType), mApnName( 2569 new char[apnLen + 1]), mApnLen(apnLen), mIpType(ipType) { 2570 2571 LOC_LOGV("AgpsMsgAtlOpenSuccess"); 2572 memcpy(mApnName, apnName, apnLen); 2573 mApnName[apnLen] = 0; 2574 } 2575 2576 inline ~AgpsMsgAtlOpenSuccess() { 2577 delete[] mApnName; 2578 } 2579 2580 inline virtual void proc() const { 2581 2582 LOC_LOGV("AgpsMsgAtlOpenSuccess::proc()"); 2583 mAgpsManager->reportAtlOpenSuccess(mAgpsType, mApnName, mApnLen, 2584 mIpType); 2585 } 2586 }; 2587 2588 sendMsg( new AgpsMsgAtlOpenSuccess( 2589 &mAgpsManager, (AGpsExtType)agpsType, apnName, apnLen, ipType)); 2590} 2591 2592void GnssAdapter::dataConnClosedCommand(AGpsExtType agpsType){ 2593 2594 LOC_LOGI("GnssAdapter::frameworkDataConnClosed"); 2595 2596 struct AgpsMsgAtlClosed: public LocMsg { 2597 2598 AgpsManager* mAgpsManager; 2599 AGpsExtType mAgpsType; 2600 2601 inline AgpsMsgAtlClosed(AgpsManager* agpsManager, AGpsExtType agpsType) : 2602 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) { 2603 2604 LOC_LOGV("AgpsMsgAtlClosed"); 2605 } 2606 2607 inline virtual void proc() const { 2608 2609 LOC_LOGV("AgpsMsgAtlClosed::proc()"); 2610 mAgpsManager->reportAtlClosed(mAgpsType); 2611 } 2612 }; 2613 2614 sendMsg( new AgpsMsgAtlClosed(&mAgpsManager, (AGpsExtType)agpsType)); 2615} 2616 2617void GnssAdapter::dataConnFailedCommand(AGpsExtType agpsType){ 2618 2619 LOC_LOGI("GnssAdapter::frameworkDataConnFailed"); 2620 2621 struct AgpsMsgAtlOpenFailed: public LocMsg { 2622 2623 AgpsManager* mAgpsManager; 2624 AGpsExtType mAgpsType; 2625 2626 inline AgpsMsgAtlOpenFailed(AgpsManager* agpsManager, AGpsExtType agpsType) : 2627 LocMsg(), mAgpsManager(agpsManager), mAgpsType(agpsType) { 2628 2629 LOC_LOGV("AgpsMsgAtlOpenFailed"); 2630 } 2631 2632 inline virtual void proc() const { 2633 2634 LOC_LOGV("AgpsMsgAtlOpenFailed::proc()"); 2635 mAgpsManager->reportAtlOpenFailed(mAgpsType); 2636 } 2637 }; 2638 2639 sendMsg( new AgpsMsgAtlOpenFailed(&mAgpsManager, (AGpsExtType)agpsType)); 2640} 2641 2642void GnssAdapter::convertSatelliteInfo(std::vector<GnssDebugSatelliteInfo>& out, 2643 const GnssSvType& in_constellation, 2644 const SystemStatusReports& in) 2645{ 2646 uint64_t sv_mask = 0ULL; 2647 uint32_t svid_min = 0; 2648 uint32_t svid_num = 0; 2649 uint32_t svid_idx = 0; 2650 2651 uint64_t eph_health_good_mask = 0ULL; 2652 uint64_t eph_health_bad_mask = 0ULL; 2653 uint64_t server_perdiction_available_mask = 0ULL; 2654 float server_perdiction_age = 0.0f; 2655 2656 // set constellationi based parameters 2657 switch (in_constellation) { 2658 case GNSS_SV_TYPE_GPS: 2659 svid_min = GNSS_BUGREPORT_GPS_MIN; 2660 svid_num = GPS_NUM; 2661 svid_idx = 0; 2662 if (!in.mSvHealth.empty()) { 2663 eph_health_good_mask = in.mSvHealth.back().mGpsGoodMask; 2664 eph_health_bad_mask = in.mSvHealth.back().mGpsBadMask; 2665 } 2666 if (!in.mXtra.empty()) { 2667 server_perdiction_available_mask = in.mXtra.back().mGpsXtraValid; 2668 server_perdiction_age = (float)(in.mXtra.back().mGpsXtraAge); 2669 } 2670 break; 2671 case GNSS_SV_TYPE_GLONASS: 2672 svid_min = GNSS_BUGREPORT_GLO_MIN; 2673 svid_num = GLO_NUM; 2674 svid_idx = GPS_NUM; 2675 if (!in.mSvHealth.empty()) { 2676 eph_health_good_mask = in.mSvHealth.back().mGloGoodMask; 2677 eph_health_bad_mask = in.mSvHealth.back().mGloBadMask; 2678 } 2679 if (!in.mXtra.empty()) { 2680 server_perdiction_available_mask = in.mXtra.back().mGloXtraValid; 2681 server_perdiction_age = (float)(in.mXtra.back().mGloXtraAge); 2682 } 2683 break; 2684 case GNSS_SV_TYPE_QZSS: 2685 svid_min = GNSS_BUGREPORT_QZSS_MIN; 2686 svid_num = QZSS_NUM; 2687 svid_idx = GPS_NUM+GLO_NUM; 2688 if (!in.mSvHealth.empty()) { 2689 eph_health_good_mask = in.mSvHealth.back().mQzssGoodMask; 2690 eph_health_bad_mask = in.mSvHealth.back().mQzssBadMask; 2691 } 2692 if (!in.mXtra.empty()) { 2693 server_perdiction_available_mask = in.mXtra.back().mQzssXtraValid; 2694 server_perdiction_age = (float)(in.mXtra.back().mQzssXtraAge); 2695 } 2696 break; 2697 case GNSS_SV_TYPE_BEIDOU: 2698 svid_min = GNSS_BUGREPORT_BDS_MIN; 2699 svid_num = BDS_NUM; 2700 svid_idx = GPS_NUM+GLO_NUM+QZSS_NUM; 2701 if (!in.mSvHealth.empty()) { 2702 eph_health_good_mask = in.mSvHealth.back().mBdsGoodMask; 2703 eph_health_bad_mask = in.mSvHealth.back().mBdsBadMask; 2704 } 2705 if (!in.mXtra.empty()) { 2706 server_perdiction_available_mask = in.mXtra.back().mBdsXtraValid; 2707 server_perdiction_age = (float)(in.mXtra.back().mBdsXtraAge); 2708 } 2709 break; 2710 case GNSS_SV_TYPE_GALILEO: 2711 svid_min = GNSS_BUGREPORT_GAL_MIN; 2712 svid_num = GAL_NUM; 2713 svid_idx = GPS_NUM+GLO_NUM+QZSS_NUM+BDS_NUM; 2714 if (!in.mSvHealth.empty()) { 2715 eph_health_good_mask = in.mSvHealth.back().mGalGoodMask; 2716 eph_health_bad_mask = in.mSvHealth.back().mGalBadMask; 2717 } 2718 if (!in.mXtra.empty()) { 2719 server_perdiction_available_mask = in.mXtra.back().mGalXtraValid; 2720 server_perdiction_age = (float)(in.mXtra.back().mGalXtraAge); 2721 } 2722 break; 2723 default: 2724 return; 2725 } 2726 2727 // extract each sv info from systemstatus report 2728 for(uint32_t i=0; i<svid_num; i++) { 2729 2730 GnssDebugSatelliteInfo s = {}; 2731 s.size = sizeof(s); 2732 s.svid = i + svid_min; 2733 s.constellation = in_constellation; 2734 2735 if (!in.mNavData.empty()) { 2736 s.mEphemerisType = in.mNavData.back().mNav[svid_idx+i].mType; 2737 s.mEphemerisSource = in.mNavData.back().mNav[svid_idx+i].mSource; 2738 } 2739 else { 2740 s.mEphemerisType = GNSS_EPH_TYPE_UNKNOWN; 2741 s.mEphemerisSource = GNSS_EPH_SOURCE_UNKNOWN; 2742 } 2743 2744 sv_mask = 0x1ULL << i; 2745 if (eph_health_good_mask & sv_mask) { 2746 s.mEphemerisHealth = GNSS_EPH_HEALTH_GOOD; 2747 } 2748 else if (eph_health_bad_mask & sv_mask) { 2749 s.mEphemerisHealth = GNSS_EPH_HEALTH_BAD; 2750 } 2751 else { 2752 s.mEphemerisHealth = GNSS_EPH_HEALTH_UNKNOWN; 2753 } 2754 2755 if (!in.mNavData.empty()) { 2756 s.ephemerisAgeSeconds = 2757 (float)(in.mNavData.back().mNav[svid_idx+i].mAgeSec); 2758 } 2759 else { 2760 s.ephemerisAgeSeconds = 0.0f; 2761 } 2762 2763 if (server_perdiction_available_mask & sv_mask) { 2764 s.serverPredictionIsAvailable = true; 2765 } 2766 else { 2767 s.serverPredictionIsAvailable = false; 2768 } 2769 2770 s.serverPredictionAgeSeconds = server_perdiction_age; 2771 out.push_back(s); 2772 } 2773 2774 return; 2775} 2776 2777bool GnssAdapter::getDebugReport(GnssDebugReport& r) 2778{ 2779 LOC_LOGD("%s]: ", __func__); 2780 2781 SystemStatus* systemstatus = LocDualContext::getSystemStatus(); 2782 if (nullptr == systemstatus) { 2783 return false; 2784 } 2785 2786 SystemStatusReports reports = {}; 2787 systemstatus->getReport(reports, true); 2788 2789 r.size = sizeof(r); 2790 2791 // location block 2792 r.mLocation.size = sizeof(r.mLocation); 2793 if(!reports.mLocation.empty() && reports.mLocation.back().mValid) { 2794 r.mLocation.mValid = true; 2795 r.mLocation.mLocation.latitude = 2796 reports.mLocation.back().mLocation.gpsLocation.latitude; 2797 r.mLocation.mLocation.longitude = 2798 reports.mLocation.back().mLocation.gpsLocation.longitude; 2799 r.mLocation.mLocation.altitude = 2800 reports.mLocation.back().mLocation.gpsLocation.altitude; 2801 r.mLocation.mLocation.speed = 2802 (double)(reports.mLocation.back().mLocation.gpsLocation.speed); 2803 r.mLocation.mLocation.bearing = 2804 (double)(reports.mLocation.back().mLocation.gpsLocation.bearing); 2805 r.mLocation.mLocation.accuracy = 2806 (double)(reports.mLocation.back().mLocation.gpsLocation.accuracy); 2807 2808 r.mLocation.verticalAccuracyMeters = 2809 reports.mLocation.back().mLocationEx.vert_unc; 2810 r.mLocation.speedAccuracyMetersPerSecond = 2811 reports.mLocation.back().mLocationEx.speed_unc; 2812 r.mLocation.bearingAccuracyDegrees = 2813 reports.mLocation.back().mLocationEx.bearing_unc; 2814 2815 r.mLocation.mUtcReported = 2816 reports.mLocation.back().mUtcReported; 2817 } 2818 else if(!reports.mBestPosition.empty() && reports.mBestPosition.back().mValid) { 2819 r.mLocation.mValid = true; 2820 r.mLocation.mLocation.latitude = 2821 (double)(reports.mBestPosition.back().mBestLat); 2822 r.mLocation.mLocation.longitude = 2823 (double)(reports.mBestPosition.back().mBestLon); 2824 r.mLocation.mLocation.altitude = 2825 reports.mBestPosition.back().mBestAlt; 2826 2827 r.mLocation.mLocation.timestamp = 2828 reports.mBestPosition.back().mUtcReported.tv_sec * 1000ULL + 2829 reports.mBestPosition.back().mUtcReported.tv_nsec / 1000000ULL; 2830 } 2831 else { 2832 r.mLocation.mValid = false; 2833 } 2834 2835 if (r.mLocation.mValid) { 2836 LOC_LOGV("getDebugReport - lat=%f lon=%f alt=%f speed=%f", 2837 r.mLocation.mLocation.latitude, 2838 r.mLocation.mLocation.longitude, 2839 r.mLocation.mLocation.altitude, 2840 r.mLocation.mLocation.speed); 2841 } 2842 2843 // time block 2844 r.mTime.size = sizeof(r.mTime); 2845 if(!reports.mTimeAndClock.empty() && reports.mTimeAndClock.back().mTimeValid) { 2846 r.mTime.mValid = true; 2847 r.mTime.timeEstimate = 2848 (((int64_t)(reports.mTimeAndClock.back().mGpsWeek)*7 + 2849 GNSS_UTC_TIME_OFFSET)*24*60*60 - 2850 (int64_t)(reports.mTimeAndClock.back().mLeapSeconds))*1000ULL + 2851 (int64_t)(reports.mTimeAndClock.back().mGpsTowMs); 2852 2853 r.mTime.timeUncertaintyNs = 2854 (float)((reports.mTimeAndClock.back().mTimeUnc + 2855 reports.mTimeAndClock.back().mLeapSecUnc)*1000); 2856 r.mTime.frequencyUncertaintyNsPerSec = 2857 (float)(reports.mTimeAndClock.back().mClockFreqBiasUnc); 2858 LOC_LOGV("getDebugReport - timeestimate=%ld unc=%f frequnc=%f", 2859 r.mTime.timeEstimate, 2860 r.mTime.timeUncertaintyNs, r.mTime.frequencyUncertaintyNsPerSec); 2861 } 2862 else { 2863 r.mTime.mValid = false; 2864 } 2865 2866 // satellite info block 2867 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GPS, reports); 2868 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GLONASS, reports); 2869 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_QZSS, reports); 2870 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_BEIDOU, reports); 2871 convertSatelliteInfo(r.mSatelliteInfo, GNSS_SV_TYPE_GALILEO, reports); 2872 LOC_LOGV("getDebugReport - satellite=%lu", r.mSatelliteInfo.size()); 2873 2874 return true; 2875} 2876 2877