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