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