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 30 #define LOG_NDDEBUG 0 31 #define LOG_TAG "LocSvc_GnssAPIClient" 32 33 #include <log_util.h> 34 #include <loc_cfg.h> 35 36 #include "LocationUtil.h" 37 #include "GnssAPIClient.h" 38 39 namespace android { 40 namespace hardware { 41 namespace gnss { 42 namespace V1_0 { 43 namespace implementation { 44 45 static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out); 46 47 GnssAPIClient::GnssAPIClient(const sp<IGnssCallback>& gpsCb, 48 const sp<IGnssNiCallback>& niCb) : 49 LocationAPIClientBase(), 50 mGnssCbIface(nullptr), 51 mGnssNiCbIface(nullptr), 52 mLocationCapabilitiesMask(0), 53 mLocationCapabilitiesCached(false) 54 { 55 LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); 56 57 // set default LocationOptions. 58 memset(&mLocationOptions, 0, sizeof(LocationOptions)); 59 mLocationOptions.size = sizeof(LocationOptions); 60 mLocationOptions.minInterval = 1000; 61 mLocationOptions.minDistance = 0; 62 mLocationOptions.mode = GNSS_SUPL_MODE_STANDALONE; 63 64 gnssUpdateCallbacks(gpsCb, niCb); 65 } 66 67 GnssAPIClient::~GnssAPIClient() 68 { 69 LOC_LOGD("%s]: ()", __FUNCTION__); 70 } 71 72 // for GpsInterface 73 void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& gpsCb, 74 const sp<IGnssNiCallback>& niCb) 75 { 76 LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); 77 78 mGnssCbIface = gpsCb; 79 mGnssNiCbIface = niCb; 80 81 LocationCallbacks locationCallbacks; 82 locationCallbacks.size = sizeof(LocationCallbacks); 83 84 locationCallbacks.trackingCb = nullptr; 85 if (mGnssCbIface != nullptr) { 86 locationCallbacks.trackingCb = [this](Location location) { 87 onTrackingCb(location); 88 }; 89 } 90 91 locationCallbacks.batchingCb = nullptr; 92 locationCallbacks.geofenceBreachCb = nullptr; 93 locationCallbacks.geofenceStatusCb = nullptr; 94 locationCallbacks.gnssLocationInfoCb = nullptr; 95 96 locationCallbacks.gnssNiCb = nullptr; 97 if (mGnssNiCbIface != nullptr) { 98 locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) { 99 onGnssNiCb(id, gnssNiNotification); 100 }; 101 } 102 103 locationCallbacks.gnssSvCb = nullptr; 104 if (mGnssCbIface != nullptr) { 105 locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) { 106 onGnssSvCb(gnssSvNotification); 107 }; 108 } 109 110 locationCallbacks.gnssNmeaCb = nullptr; 111 if (mGnssCbIface != nullptr) { 112 locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) { 113 onGnssNmeaCb(gnssNmeaNotification); 114 }; 115 } 116 117 locationCallbacks.gnssMeasurementsCb = nullptr; 118 119 locAPISetCallbacks(locationCallbacks); 120 } 121 122 bool GnssAPIClient::gnssStart() 123 { 124 LOC_LOGD("%s]: ()", __FUNCTION__); 125 bool retVal = true; 126 locAPIStartTracking(mLocationOptions); 127 return retVal; 128 } 129 130 bool GnssAPIClient::gnssStop() 131 { 132 LOC_LOGD("%s]: ()", __FUNCTION__); 133 bool retVal = true; 134 locAPIStopTracking(); 135 return retVal; 136 } 137 138 void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags) 139 { 140 LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags); 141 GnssAidingData data; 142 memset(&data, 0, sizeof (GnssAidingData)); 143 data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT | 144 GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT | 145 GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT | 146 GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT | 147 GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT; 148 149 if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL) 150 data.deleteAll = true; 151 else { 152 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS) 153 data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT; 154 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC) 155 data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT; 156 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION) 157 data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT; 158 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME) 159 data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT; 160 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO) 161 data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT; 162 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC) 163 data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT; 164 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH) 165 data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT; 166 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR) 167 data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT; 168 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER) 169 data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT; 170 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA) 171 data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT; 172 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI) 173 data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT; 174 if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO) 175 data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT; 176 } 177 locAPIGnssDeleteAidingData(data); 178 } 179 180 bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode, 181 IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs, 182 uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs) 183 { 184 LOC_LOGD("%s]: (%d %d %d %d %d)", __FUNCTION__, 185 (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters, preferredTimeMs); 186 bool retVal = true; 187 memset(&mLocationOptions, 0, sizeof(LocationOptions)); 188 mLocationOptions.size = sizeof(LocationOptions); 189 mLocationOptions.minInterval = minIntervalMs; 190 mLocationOptions.minDistance = preferredAccuracyMeters; 191 if (mode == IGnss::GnssPositionMode::STANDALONE) 192 mLocationOptions.mode = GNSS_SUPL_MODE_STANDALONE; 193 else if (mode == IGnss::GnssPositionMode::MS_BASED) 194 mLocationOptions.mode = GNSS_SUPL_MODE_MSB; 195 else if (mode == IGnss::GnssPositionMode::MS_ASSISTED) 196 mLocationOptions.mode = GNSS_SUPL_MODE_MSA; 197 locAPIUpdateTrackingOptions(mLocationOptions); 198 return retVal; 199 } 200 201 // for GpsNiInterface 202 void GnssAPIClient::gnssNiRespond(int32_t notifId, 203 IGnssNiCallback::GnssUserResponseType userResponse) 204 { 205 LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<int>(userResponse)); 206 GnssNiResponse data = GNSS_NI_RESPONSE_IGNORE; 207 if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT) 208 data = GNSS_NI_RESPONSE_ACCEPT; 209 else if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY) 210 data = GNSS_NI_RESPONSE_DENY; 211 else if (userResponse == IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP) 212 data = GNSS_NI_RESPONSE_NO_RESPONSE; 213 locAPIGnssNiResponse(notifId, data); 214 } 215 216 // for GnssConfigurationInterface 217 void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig) 218 { 219 LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags); 220 locAPIGnssUpdateConfig(gnssConfig); 221 } 222 223 void GnssAPIClient::requestCapabilities() { 224 // only send capablities if it's already cached, otherwise the first time LocationAPI 225 // is initialized, capabilities will be sent by LocationAPI 226 if (mLocationCapabilitiesCached) { 227 onCapabilitiesCb(mLocationCapabilitiesMask); 228 } 229 } 230 231 // callbacks 232 void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) 233 { 234 LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask); 235 mLocationCapabilitiesMask = capabilitiesMask; 236 mLocationCapabilitiesCached = true; 237 sp<IGnssCallback> gnssCbIface = mGnssCbIface; 238 239 if (gnssCbIface != nullptr) { 240 uint32_t data = 0; 241 if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) || 242 (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) || 243 (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) || 244 (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT)) 245 data |= IGnssCallback::Capabilities::SCHEDULING; 246 if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT) 247 data |= IGnssCallback::Capabilities::GEOFENCING; 248 if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) 249 data |= IGnssCallback::Capabilities::MEASUREMENTS; 250 if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT) 251 data |= IGnssCallback::Capabilities::MSB; 252 if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT) 253 data |= IGnssCallback::Capabilities::MSA; 254 auto r = gnssCbIface->gnssSetCapabilitesCb(data); 255 if (!r.isOk()) { 256 LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s", 257 __func__, r.description().c_str()); 258 } 259 } 260 if (gnssCbIface != nullptr) { 261 IGnssCallback::GnssSystemInfo gnssInfo; 262 gnssInfo.yearOfHw = 2015; 263 if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) { 264 gnssInfo.yearOfHw = 2017; 265 } 266 LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw); 267 auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo); 268 if (!r.isOk()) { 269 LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s", 270 __func__, r.description().c_str()); 271 } 272 } 273 } 274 275 void GnssAPIClient::onTrackingCb(Location location) 276 { 277 LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags); 278 sp<IGnssCallback> gnssCbIface = mGnssCbIface; 279 280 if (gnssCbIface != nullptr) { 281 GnssLocation gnssLocation; 282 convertGnssLocation(location, gnssLocation); 283 auto r = gnssCbIface->gnssLocationCb(gnssLocation); 284 if (!r.isOk()) { 285 LOC_LOGE("%s] Error from gnssLocationCb description=%s", 286 __func__, r.description().c_str()); 287 } 288 } 289 } 290 291 void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) 292 { 293 LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id); 294 sp<IGnssNiCallback> gnssNiCbIface = mGnssNiCbIface; 295 296 if (gnssNiCbIface == nullptr) { 297 LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__); 298 return; 299 } 300 301 IGnssNiCallback::GnssNiNotification notificationGnss = {}; 302 303 notificationGnss.notificationId = id; 304 305 if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE) 306 notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE; 307 else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL) 308 notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL; 309 else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE) 310 notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE; 311 else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL) 312 notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL; 313 314 if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT) 315 notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY; 316 if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT) 317 notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY; 318 if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT) 319 notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE; 320 321 notificationGnss.timeoutSec = gnssNiNotification.timeout; 322 323 if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT) 324 notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT; 325 else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY) 326 notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY; 327 else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE || 328 gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE) 329 notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP; 330 331 notificationGnss.requestorId = gnssNiNotification.requestor; 332 333 notificationGnss.notificationMessage = gnssNiNotification.message; 334 335 if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE) 336 notificationGnss.requestorIdEncoding = 337 IGnssNiCallback::GnssNiEncodingType::ENC_NONE; 338 else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT) 339 notificationGnss.requestorIdEncoding = 340 IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT; 341 else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8) 342 notificationGnss.requestorIdEncoding = 343 IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8; 344 else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2) 345 notificationGnss.requestorIdEncoding = 346 IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2; 347 348 if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE) 349 notificationGnss.notificationIdEncoding = 350 IGnssNiCallback::GnssNiEncodingType::ENC_NONE; 351 else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT) 352 notificationGnss.notificationIdEncoding = 353 IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT; 354 else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8) 355 notificationGnss.notificationIdEncoding = 356 IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8; 357 else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2) 358 notificationGnss.notificationIdEncoding = 359 IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2; 360 361 gnssNiCbIface->niNotifyCb(notificationGnss); 362 } 363 364 void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification) 365 { 366 LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count); 367 sp<IGnssCallback> gnssCbIface = mGnssCbIface; 368 369 if (gnssCbIface != nullptr) { 370 IGnssCallback::GnssSvStatus svStatus; 371 convertGnssSvStatus(gnssSvNotification, svStatus); 372 auto r = gnssCbIface->gnssSvStatusCb(svStatus); 373 if (!r.isOk()) { 374 LOC_LOGE("%s] Error from gnssSvStatusCb description=%s", 375 __func__, r.description().c_str()); 376 } 377 } 378 } 379 380 void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) 381 { 382 sp<IGnssCallback> gnssCbIface = mGnssCbIface; 383 384 if (gnssCbIface != nullptr) { 385 android::hardware::hidl_string nmeaString; 386 nmeaString.setToExternal(gnssNmeaNotification.nmea, gnssNmeaNotification.length); 387 auto r = gnssCbIface->gnssNmeaCb( 388 static_cast<GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString); 389 if (!r.isOk()) { 390 LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%u description=%s", __func__, 391 gnssNmeaNotification.nmea, gnssNmeaNotification.length, r.description().c_str()); 392 } 393 } 394 } 395 396 void GnssAPIClient::onStartTrackingCb(LocationError error) 397 { 398 LOC_LOGD("%s]: (%d)", __FUNCTION__, error); 399 sp<IGnssCallback> gnssCbIface = mGnssCbIface; 400 401 if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { 402 auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON); 403 if (!r.isOk()) { 404 LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s", 405 __func__, r.description().c_str()); 406 } 407 r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN); 408 if (!r.isOk()) { 409 LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s", 410 __func__, r.description().c_str()); 411 } 412 } 413 } 414 415 void GnssAPIClient::onStopTrackingCb(LocationError error) 416 { 417 LOC_LOGD("%s]: (%d)", __FUNCTION__, error); 418 sp<IGnssCallback> gnssCbIface = mGnssCbIface; 419 420 if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { 421 auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END); 422 if (!r.isOk()) { 423 LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s", 424 __func__, r.description().c_str()); 425 } 426 r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF); 427 if (!r.isOk()) { 428 LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s", 429 __func__, r.description().c_str()); 430 } 431 } 432 } 433 434 static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out) 435 { 436 memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus)); 437 out.numSvs = in.count; 438 if (out.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) { 439 LOC_LOGW("%s]: Too many satellites %zd. Clamps to %d.", 440 __FUNCTION__, out.numSvs, GnssMax::SVS_COUNT); 441 out.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT); 442 } 443 for (size_t i = 0; i < out.numSvs; i++) { 444 IGnssCallback::GnssSvInfo& info = out.gnssSvList[i]; 445 info.svid = in.gnssSvs[i].svId; 446 convertGnssConstellationType(in.gnssSvs[i].type, info.constellation); 447 info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz; 448 info.elevationDegrees = in.gnssSvs[i].elevation; 449 info.azimuthDegrees = in.gnssSvs[i].azimuth; 450 info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz; 451 info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE); 452 if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT) 453 info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA; 454 if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT) 455 info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA; 456 if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT) 457 info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX; 458 if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT) 459 info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY; 460 } 461 } 462 463 } // namespace implementation 464 } // namespace V1_0 465 } // namespace gnss 466 } // namespace hardware 467 } // namespace android 468