1/* Copyright (c) 2011-2014,2016 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_NDDEBUG 0 30#define LOG_TAG "LocSvc_LocApiBase" 31 32#include <dlfcn.h> 33#include <LocApiBase.h> 34#include <LocAdapterBase.h> 35#include <platform_lib_log_util.h> 36#include <LocDualContext.h> 37 38namespace loc_core { 39 40#define TO_ALL_LOCADAPTERS(call) TO_ALL_ADAPTERS(mLocAdapters, (call)) 41#define TO_1ST_HANDLING_LOCADAPTERS(call) TO_1ST_HANDLING_ADAPTER(mLocAdapters, (call)) 42 43int hexcode(char *hexstring, int string_size, 44 const char *data, int data_size) 45{ 46 int i; 47 for (i = 0; i < data_size; i++) 48 { 49 char ch = data[i]; 50 if (i*2 + 3 <= string_size) 51 { 52 snprintf(&hexstring[i*2], 3, "%02X", ch); 53 } 54 else { 55 break; 56 } 57 } 58 return i; 59} 60 61int decodeAddress(char *addr_string, int string_size, 62 const char *data, int data_size) 63{ 64 const char addr_prefix = 0x91; 65 int i, idxOutput = 0; 66 67 if (!data || !addr_string) { return 0; } 68 69 if (data[0] != addr_prefix) 70 { 71 LOC_LOGW("decodeAddress: address prefix is not 0x%x but 0x%x", addr_prefix, data[0]); 72 addr_string[0] = '\0'; 73 return 0; // prefix not correct 74 } 75 76 for (i = 1; i < data_size; i++) 77 { 78 unsigned char ch = data[i], low = ch & 0x0F, hi = ch >> 4; 79 if (low <= 9 && idxOutput < string_size - 1) { addr_string[idxOutput++] = low + '0'; } 80 if (hi <= 9 && idxOutput < string_size - 1) { addr_string[idxOutput++] = hi + '0'; } 81 } 82 83 addr_string[idxOutput] = '\0'; // Terminates the string 84 85 return idxOutput; 86} 87 88struct LocSsrMsg : public LocMsg { 89 LocApiBase* mLocApi; 90 inline LocSsrMsg(LocApiBase* locApi) : 91 LocMsg(), mLocApi(locApi) 92 { 93 locallog(); 94 } 95 inline virtual void proc() const { 96 mLocApi->close(); 97 mLocApi->open(mLocApi->getEvtMask()); 98 } 99 inline void locallog() { 100 LOC_LOGV("LocSsrMsg"); 101 } 102 inline virtual void log() { 103 locallog(); 104 } 105}; 106 107struct LocOpenMsg : public LocMsg { 108 LocApiBase* mLocApi; 109 LOC_API_ADAPTER_EVENT_MASK_T mMask; 110 inline LocOpenMsg(LocApiBase* locApi, 111 LOC_API_ADAPTER_EVENT_MASK_T mask) : 112 LocMsg(), mLocApi(locApi), mMask(mask) 113 { 114 locallog(); 115 } 116 inline virtual void proc() const { 117 mLocApi->open(mMask); 118 } 119 inline void locallog() { 120 LOC_LOGV("%s:%d]: LocOpen Mask: %x\n", 121 __func__, __LINE__, mMask); 122 } 123 inline virtual void log() { 124 locallog(); 125 } 126}; 127 128LocApiBase::LocApiBase(const MsgTask* msgTask, 129 LOC_API_ADAPTER_EVENT_MASK_T excludedMask, 130 ContextBase* context) : 131 mExcludedMask(excludedMask), mMsgTask(msgTask), 132 mMask(0), mSupportedMsg(0), mContext(context) 133{ 134 memset(mLocAdapters, 0, sizeof(mLocAdapters)); 135 memset(mFeaturesSupported, 0, sizeof(mFeaturesSupported)); 136} 137 138LOC_API_ADAPTER_EVENT_MASK_T LocApiBase::getEvtMask() 139{ 140 LOC_API_ADAPTER_EVENT_MASK_T mask = 0; 141 142 TO_ALL_LOCADAPTERS(mask |= mLocAdapters[i]->getEvtMask()); 143 144 return mask & ~mExcludedMask; 145} 146 147bool LocApiBase::isInSession() 148{ 149 bool inSession = false; 150 151 for (int i = 0; 152 !inSession && i < MAX_ADAPTERS && NULL != mLocAdapters[i]; 153 i++) { 154 inSession = mLocAdapters[i]->isInSession(); 155 } 156 157 return inSession; 158} 159 160void LocApiBase::addAdapter(LocAdapterBase* adapter) 161{ 162 for (int i = 0; i < MAX_ADAPTERS && mLocAdapters[i] != adapter; i++) { 163 if (mLocAdapters[i] == NULL) { 164 mLocAdapters[i] = adapter; 165 mMsgTask->sendMsg(new LocOpenMsg(this, 166 (adapter->getEvtMask()))); 167 break; 168 } 169 } 170} 171 172void LocApiBase::removeAdapter(LocAdapterBase* adapter) 173{ 174 for (int i = 0; 175 i < MAX_ADAPTERS && NULL != mLocAdapters[i]; 176 i++) { 177 if (mLocAdapters[i] == adapter) { 178 mLocAdapters[i] = NULL; 179 180 // shift the rest of the adapters up so that the pointers 181 // in the array do not have holes. This should be more 182 // performant, because the array maintenance is much much 183 // less frequent than event handlings, which need to linear 184 // search all the adapters 185 int j = i; 186 while (++i < MAX_ADAPTERS && mLocAdapters[i] != NULL); 187 188 // i would be MAX_ADAPTERS or point to a NULL 189 i--; 190 // i now should point to a none NULL adapter within valid 191 // range although i could be equal to j, but it won't hurt. 192 // No need to check it, as it gains nothing. 193 mLocAdapters[j] = mLocAdapters[i]; 194 // this makes sure that we exit the for loop 195 mLocAdapters[i] = NULL; 196 197 // if we have an empty list of adapters 198 if (0 == i) { 199 close(); 200 } else { 201 // else we need to remove the bit 202 mMsgTask->sendMsg(new LocOpenMsg(this, getEvtMask())); 203 } 204 } 205 } 206} 207 208void LocApiBase::updateEvtMask() 209{ 210 mMsgTask->sendMsg(new LocOpenMsg(this, getEvtMask())); 211} 212 213void LocApiBase::handleEngineUpEvent() 214{ 215 // This will take care of renegotiating the loc handle 216 mMsgTask->sendMsg(new LocSsrMsg(this)); 217 218 LocDualContext::injectFeatureConfig(mContext); 219 220 // loop through adapters, and deliver to all adapters. 221 TO_ALL_LOCADAPTERS(mLocAdapters[i]->handleEngineUpEvent()); 222} 223 224void LocApiBase::handleEngineDownEvent() 225{ 226 // loop through adapters, and deliver to all adapters. 227 TO_ALL_LOCADAPTERS(mLocAdapters[i]->handleEngineDownEvent()); 228} 229 230void LocApiBase::reportPosition(UlpLocation &location, 231 GpsLocationExtended &locationExtended, 232 void* locationExt, 233 enum loc_sess_status status, 234 LocPosTechMask loc_technology_mask) 235{ 236 // print the location info before delivering 237 LOC_LOGV("flags: %d\n source: %d\n latitude: %f\n longitude: %f\n " 238 "altitude: %f\n speed: %f\n bearing: %f\n accuracy: %f\n " 239 "timestamp: %lld\n rawDataSize: %d\n rawData: %p\n " 240 "Session status: %d\n Technology mask: %u\n " 241 "SV used in fix (gps/glo/bds/gal) : (%x/%x/%x/%x)", 242 location.gpsLocation.flags, location.position_source, 243 location.gpsLocation.latitude, location.gpsLocation.longitude, 244 location.gpsLocation.altitude, location.gpsLocation.speed, 245 location.gpsLocation.bearing, location.gpsLocation.accuracy, 246 location.gpsLocation.timestamp, location.rawDataSize, 247 location.rawData, status, loc_technology_mask, 248 locationExtended.gnss_sv_used_ids.gps_sv_used_ids_mask, 249 locationExtended.gnss_sv_used_ids.glo_sv_used_ids_mask, 250 locationExtended.gnss_sv_used_ids.bds_sv_used_ids_mask, 251 locationExtended.gnss_sv_used_ids.gal_sv_used_ids_mask); 252 // loop through adapters, and deliver to all adapters. 253 TO_ALL_LOCADAPTERS( 254 mLocAdapters[i]->reportPosition(location, 255 locationExtended, 256 locationExt, 257 status, 258 loc_technology_mask) 259 ); 260} 261 262void LocApiBase::reportWwanZppFix(GpsLocation &zppLoc) 263{ 264 // loop through adapters, and deliver to the first handling adapter. 265 TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportWwanZppFix(zppLoc)); 266} 267 268void LocApiBase::reportSv(GnssSvStatus &svStatus, 269 GpsLocationExtended &locationExtended, 270 void* svExt) 271{ 272 const char* constellationString[] = { "Unknown", "GPS", "SBAS", "GLONASS", 273 "QZSS", "BEIDOU", "GALILEO" }; 274 275 // print the SV info before delivering 276 LOC_LOGV("num sv: %d\n" 277 " sv: constellation svid cN0" 278 " elevation azimuth flags", 279 svStatus.num_svs); 280 for (int i = 0; i < svStatus.num_svs && i < GNSS_MAX_SVS; i++) { 281 if (svStatus.gnss_sv_list[i].constellation > 282 sizeof(constellationString) / sizeof(constellationString[0]) - 1) { 283 svStatus.gnss_sv_list[i].constellation = 0; 284 } 285 LOC_LOGV(" %03d: %*s %02d %f %f %f 0x%02X", 286 i, 287 13, 288 constellationString[svStatus.gnss_sv_list[i].constellation], 289 svStatus.gnss_sv_list[i].svid, 290 svStatus.gnss_sv_list[i].c_n0_dbhz, 291 svStatus.gnss_sv_list[i].elevation, 292 svStatus.gnss_sv_list[i].azimuth, 293 svStatus.gnss_sv_list[i].flags); 294 } 295 // loop through adapters, and deliver to all adapters. 296 TO_ALL_LOCADAPTERS( 297 mLocAdapters[i]->reportSv(svStatus, 298 locationExtended, 299 svExt) 300 ); 301} 302 303void LocApiBase::reportSvMeasurement(GnssSvMeasurementSet &svMeasurementSet) 304{ 305 // loop through adapters, and deliver to all adapters. 306 TO_ALL_LOCADAPTERS( 307 mLocAdapters[i]->reportSvMeasurement(svMeasurementSet) 308 ); 309} 310 311void LocApiBase::reportSvPolynomial(GnssSvPolynomial &svPolynomial) 312{ 313 // loop through adapters, and deliver to all adapters. 314 TO_ALL_LOCADAPTERS( 315 mLocAdapters[i]->reportSvPolynomial(svPolynomial) 316 ); 317} 318 319void LocApiBase::reportStatus(GpsStatusValue status) 320{ 321 // loop through adapters, and deliver to all adapters. 322 TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportStatus(status)); 323} 324 325void LocApiBase::reportNmea(const char* nmea, int length) 326{ 327 // loop through adapters, and deliver to all adapters. 328 TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportNmea(nmea, length)); 329} 330 331void LocApiBase::reportXtraServer(const char* url1, const char* url2, 332 const char* url3, const int maxlength) 333{ 334 // loop through adapters, and deliver to the first handling adapter. 335 TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportXtraServer(url1, url2, url3, maxlength)); 336 337} 338 339void LocApiBase::requestXtraData() 340{ 341 // loop through adapters, and deliver to the first handling adapter. 342 TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestXtraData()); 343} 344 345void LocApiBase::requestTime() 346{ 347 // loop through adapters, and deliver to the first handling adapter. 348 TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestTime()); 349} 350 351void LocApiBase::requestLocation() 352{ 353 // loop through adapters, and deliver to the first handling adapter. 354 TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestLocation()); 355} 356 357void LocApiBase::requestATL(int connHandle, AGpsType agps_type) 358{ 359 // loop through adapters, and deliver to the first handling adapter. 360 TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestATL(connHandle, agps_type)); 361} 362 363void LocApiBase::releaseATL(int connHandle) 364{ 365 // loop through adapters, and deliver to the first handling adapter. 366 TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->releaseATL(connHandle)); 367} 368 369void LocApiBase::requestSuplES(int connHandle) 370{ 371 // loop through adapters, and deliver to the first handling adapter. 372 TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestSuplES(connHandle)); 373} 374 375void LocApiBase::reportDataCallOpened() 376{ 377 // loop through adapters, and deliver to the first handling adapter. 378 TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportDataCallOpened()); 379} 380 381void LocApiBase::reportDataCallClosed() 382{ 383 // loop through adapters, and deliver to the first handling adapter. 384 TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->reportDataCallClosed()); 385} 386 387void LocApiBase::requestNiNotify(GpsNiNotification ¬ify, const void* data) 388{ 389 // loop through adapters, and deliver to the first handling adapter. 390 TO_1ST_HANDLING_LOCADAPTERS(mLocAdapters[i]->requestNiNotify(notify, data)); 391} 392 393void LocApiBase::saveSupportedMsgList(uint64_t supportedMsgList) 394{ 395 mSupportedMsg = supportedMsgList; 396} 397 398void LocApiBase::saveSupportedFeatureList(uint8_t *featureList) 399{ 400 memcpy((void *)mFeaturesSupported, (void *)featureList, sizeof(mFeaturesSupported)); 401} 402 403void* LocApiBase :: getSibling() 404 DEFAULT_IMPL(NULL) 405 406LocApiProxyBase* LocApiBase :: getLocApiProxy() 407 DEFAULT_IMPL(NULL) 408 409void LocApiBase::reportGnssMeasurementData(GnssData &gnssMeasurementData) 410{ 411 // loop through adapters, and deliver to all adapters. 412 TO_ALL_LOCADAPTERS(mLocAdapters[i]->reportGnssMeasurementData(gnssMeasurementData)); 413} 414 415enum loc_api_adapter_err LocApiBase:: 416 open(LOC_API_ADAPTER_EVENT_MASK_T mask) 417DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 418 419enum loc_api_adapter_err LocApiBase:: 420 close() 421DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 422 423enum loc_api_adapter_err LocApiBase:: 424 startFix(const LocPosMode& posMode) 425DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 426 427enum loc_api_adapter_err LocApiBase:: 428 stopFix() 429DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 430 431enum loc_api_adapter_err LocApiBase:: 432 deleteAidingData(GpsAidingData f) 433DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 434 435enum loc_api_adapter_err LocApiBase:: 436 enableData(int enable) 437DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 438 439enum loc_api_adapter_err LocApiBase:: 440 setAPN(char* apn, int len) 441DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 442 443enum loc_api_adapter_err LocApiBase:: 444 injectPosition(double latitude, double longitude, float accuracy) 445DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 446 447enum loc_api_adapter_err LocApiBase:: 448 setTime(GpsUtcTime time, int64_t timeReference, int uncertainty) 449DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 450 451enum loc_api_adapter_err LocApiBase:: 452 setXtraData(char* data, int length) 453DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 454 455enum loc_api_adapter_err LocApiBase:: 456 requestXtraServer() 457DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 458 459enum loc_api_adapter_err LocApiBase:: 460 atlOpenStatus(int handle, int is_succ, char* apn, 461 AGpsBearerType bear, AGpsType agpsType) 462DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 463 464enum loc_api_adapter_err LocApiBase:: 465 atlCloseStatus(int handle, int is_succ) 466DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 467 468enum loc_api_adapter_err LocApiBase:: 469 setPositionMode(const LocPosMode& posMode) 470DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 471 472enum loc_api_adapter_err LocApiBase:: 473 setServer(const char* url, int len) 474DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 475 476enum loc_api_adapter_err LocApiBase:: 477 setServer(unsigned int ip, int port, 478 LocServerType type) 479DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 480 481enum loc_api_adapter_err LocApiBase:: 482 informNiResponse(GpsUserResponseType userResponse, 483 const void* passThroughData) 484DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 485 486enum loc_api_adapter_err LocApiBase:: 487 setSUPLVersion(uint32_t version) 488DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 489 490enum loc_api_adapter_err LocApiBase:: 491 setNMEATypes (uint32_t typesMask) 492DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 493 494enum loc_api_adapter_err LocApiBase:: 495 setLPPConfig(uint32_t profile) 496DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 497 498enum loc_api_adapter_err LocApiBase:: 499 setSensorControlConfig(int sensorUsage, 500 int sensorProvider) 501DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 502 503enum loc_api_adapter_err LocApiBase:: 504 setSensorProperties(bool gyroBiasVarianceRandomWalk_valid, 505 float gyroBiasVarianceRandomWalk, 506 bool accelBiasVarianceRandomWalk_valid, 507 float accelBiasVarianceRandomWalk, 508 bool angleBiasVarianceRandomWalk_valid, 509 float angleBiasVarianceRandomWalk, 510 bool rateBiasVarianceRandomWalk_valid, 511 float rateBiasVarianceRandomWalk, 512 bool velocityBiasVarianceRandomWalk_valid, 513 float velocityBiasVarianceRandomWalk) 514DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 515 516enum loc_api_adapter_err LocApiBase:: 517 setSensorPerfControlConfig(int controlMode, 518 int accelSamplesPerBatch, 519 int accelBatchesPerSec, 520 int gyroSamplesPerBatch, 521 int gyroBatchesPerSec, 522 int accelSamplesPerBatchHigh, 523 int accelBatchesPerSecHigh, 524 int gyroSamplesPerBatchHigh, 525 int gyroBatchesPerSecHigh, 526 int algorithmConfig) 527DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 528 529enum loc_api_adapter_err LocApiBase:: 530 setAGLONASSProtocol(unsigned long aGlonassProtocol) 531DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 532 533enum loc_api_adapter_err LocApiBase:: 534 setLPPeProtocol(unsigned long lppeCP, unsigned long lppeUP) 535 DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 536 537enum loc_api_adapter_err LocApiBase:: 538 getWwanZppFix() 539DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 540 541enum loc_api_adapter_err LocApiBase:: 542 getBestAvailableZppFix(GpsLocation& zppLoc) 543{ 544 memset(&zppLoc, 0, sizeof(zppLoc)); 545 DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 546} 547 548enum loc_api_adapter_err LocApiBase:: 549 getBestAvailableZppFix(GpsLocation & zppLoc, LocPosTechMask & tech_mask) 550{ 551 memset(&zppLoc, 0, sizeof(zppLoc)); 552 memset(&tech_mask, 0, sizeof(tech_mask)); 553 DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 554} 555 556int LocApiBase:: 557 initDataServiceClient(bool isDueToSsr) 558DEFAULT_IMPL(-1) 559 560int LocApiBase:: 561 openAndStartDataCall() 562DEFAULT_IMPL(-1) 563 564void LocApiBase:: 565 stopDataCall() 566DEFAULT_IMPL() 567 568void LocApiBase:: 569 closeDataCall() 570DEFAULT_IMPL() 571 572void LocApiBase:: 573 releaseDataServiceClient() 574DEFAULT_IMPL() 575 576int LocApiBase:: 577 setGpsLock(LOC_GPS_LOCK_MASK lock) 578DEFAULT_IMPL(-1) 579 580void LocApiBase:: 581 installAGpsCert(const DerEncodedCertificate* pData, 582 size_t length, 583 uint32_t slotBitMask) 584DEFAULT_IMPL() 585 586int LocApiBase:: 587 getGpsLock() 588DEFAULT_IMPL(-1) 589 590enum loc_api_adapter_err LocApiBase:: 591 setXtraVersionCheck(enum xtra_version_check check) 592DEFAULT_IMPL(LOC_API_ADAPTER_ERR_SUCCESS) 593 594bool LocApiBase:: 595 gnssConstellationConfig() 596DEFAULT_IMPL(false) 597 598bool LocApiBase:: 599 isFeatureSupported(uint8_t featureVal) 600{ 601 uint8_t arrayIndex = featureVal >> 3; 602 uint8_t bitPos = featureVal & 7; 603 604 if (arrayIndex >= MAX_FEATURE_LENGTH) return false; 605 return ((mFeaturesSupported[arrayIndex] >> bitPos ) & 0x1); 606} 607 608} // namespace loc_core 609