1 /* Copyright (c) 2011-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_EngAdapter" 31 32 #include <sys/stat.h> 33 #include <errno.h> 34 #include <ctype.h> 35 #include <cutils/properties.h> 36 #include <LocEngAdapter.h> 37 #include "loc_eng_msg.h" 38 #include "loc_log.h" 39 40 #define CHIPSET_SERIAL_NUMBER_MAX_LEN 16 41 #define USER_AGENT_MAX_LEN 512 42 43 using namespace loc_core; 44 45 LocInternalAdapter::LocInternalAdapter(LocEngAdapter* adapter) : 46 LocAdapterBase(adapter->getMsgTask()), 47 mLocEngAdapter(adapter) 48 { 49 } 50 void LocInternalAdapter::setPositionModeInt(LocPosMode& posMode) { 51 sendMsg(new LocEngPositionMode(mLocEngAdapter, posMode)); 52 } 53 void LocInternalAdapter::startFixInt() { 54 sendMsg(new LocEngStartFix(mLocEngAdapter)); 55 } 56 void LocInternalAdapter::stopFixInt() { 57 sendMsg(new LocEngStopFix(mLocEngAdapter)); 58 } 59 void LocInternalAdapter::getZppInt() { 60 sendMsg(new LocEngGetZpp(mLocEngAdapter)); 61 } 62 63 LocEngAdapter::LocEngAdapter(LOC_API_ADAPTER_EVENT_MASK_T mask, 64 void* owner, ContextBase* context, 65 LocThread::tCreate tCreator) : 66 LocAdapterBase(mask, 67 //Get the AFW context if VzW context has not already been intialized in 68 //loc_ext 69 context == NULL? 70 LocDualContext::getLocFgContext(tCreator, 71 NULL, 72 LocDualContext::mLocationHalName, 73 false) 74 :context), 75 mOwner(owner), mInternalAdapter(new LocInternalAdapter(this)), 76 mUlp(new UlpProxyBase()), mNavigating(false), 77 mSupportsAgpsRequests(false), 78 mSupportsPositionInjection(false), 79 mSupportsTimeInjection(false), 80 mPowerVote(0) 81 { 82 memset(&mFixCriteria, 0, sizeof(mFixCriteria)); 83 mFixCriteria.mode = LOC_POSITION_MODE_INVALID; 84 LOC_LOGD("LocEngAdapter created"); 85 } 86 87 inline 88 LocEngAdapter::~LocEngAdapter() 89 { 90 delete mInternalAdapter; 91 LOC_LOGV("LocEngAdapter deleted"); 92 } 93 94 void LocEngAdapter::setXtraUserAgent() { 95 struct LocSetXtraUserAgent : public LocMsg { 96 const ContextBase* const mContext; 97 inline LocSetXtraUserAgent(ContextBase* context) : 98 LocMsg(), mContext(context) { 99 } 100 virtual void proc() const { 101 char release[PROPERTY_VALUE_MAX]; 102 char manufacture[PROPERTY_VALUE_MAX]; 103 char model[PROPERTY_VALUE_MAX]; 104 char board[PROPERTY_VALUE_MAX]; 105 char brand[PROPERTY_VALUE_MAX]; 106 char chipsetsn[CHIPSET_SERIAL_NUMBER_MAX_LEN]; 107 char userAgent[USER_AGENT_MAX_LEN]; 108 const char defVal[] = "-"; 109 110 property_get("ro.build.version.release", release, defVal); 111 property_get("ro.product.manufacturer", manufacture, defVal); 112 property_get("ro.product.model", model, defVal); 113 property_get("ro.product.board", board, defVal); 114 property_get("ro.product.brand", brand, defVal); 115 getChipsetSerialNo(chipsetsn, sizeof(chipsetsn), defVal); 116 117 encodeInPlace(release, PROPERTY_VALUE_MAX); 118 encodeInPlace(manufacture, PROPERTY_VALUE_MAX); 119 encodeInPlace(model, PROPERTY_VALUE_MAX); 120 encodeInPlace(board, PROPERTY_VALUE_MAX); 121 encodeInPlace(brand, PROPERTY_VALUE_MAX); 122 123 snprintf(userAgent, sizeof(userAgent), "A/%s/%s/%s/%s/-/QCX3/s%u/-/%s/-/%s/-/-/-", 124 release, manufacture, model, board, 125 mContext->getIzatDevId(), chipsetsn, brand); 126 127 for (int i = 0; i < sizeof(userAgent) && userAgent[i]; i++) { 128 if (' ' == userAgent[i]) userAgent[i] = '#'; 129 } 130 131 saveUserAgentString(userAgent, strlen(userAgent)); 132 LOC_LOGV("%s] UserAgent %s", __func__, userAgent); 133 } 134 135 void saveUserAgentString(const char* data, const int len) const { 136 const char XTRA_FOLDER[] = "/data/misc/location/xtra"; 137 const char USER_AGENT_FILE[] = "/data/misc/location/xtra/useragent.txt"; 138 139 if (data == NULL || len < 1) { 140 LOC_LOGE("%s:%d]: invalid input data = %p len = %d", __func__, __LINE__, data, len); 141 return; 142 } 143 144 struct stat s; 145 int err = stat(XTRA_FOLDER, &s); 146 if (err < 0) { 147 if (ENOENT == errno) { 148 if (mkdir(XTRA_FOLDER, 0700) < 0) { 149 LOC_LOGE("%s:%d]: make XTRA_FOLDER failed", __func__, __LINE__); 150 return; 151 } 152 } else { 153 LOC_LOGE("%s:%d]: XTRA_FOLDER invalid", __func__, __LINE__); 154 return; 155 } 156 } 157 158 FILE* file = fopen(USER_AGENT_FILE, "wt"); 159 if (file == NULL) { 160 LOC_LOGE("%s:%d]: open USER_AGENT_FILE failed", __func__, __LINE__); 161 return; 162 } 163 164 size_t written = fwrite(data, 1, len, file); 165 fclose(file); 166 file = NULL; 167 168 // set file permission 169 chmod(USER_AGENT_FILE, 0600); 170 171 if (written != len) { 172 LOC_LOGE("%s:%d]: write USER_AGENT_FILE failed", __func__, __LINE__); 173 } 174 } 175 176 void getChipsetSerialNo(char buf[], int buflen, const char def[]) const { 177 const char SOC_SERIAL_NUMBER[] = "/sys/devices/soc0/serial_number"; 178 179 FILE* file = fopen(SOC_SERIAL_NUMBER, "rt"); 180 if (file == NULL) { 181 // use default upon unreadable file 182 strlcpy(buf, def, buflen); 183 184 } else { 185 size_t size = fread(buf, 1, buflen - 1, file); 186 if (size == 0) { 187 // use default upon empty file 188 strlcpy(buf, def, buflen); 189 190 } else { 191 buf[size] = '\0'; 192 } 193 194 fclose(file); 195 196 // remove trailing spaces 197 size_t len = strlen(buf); 198 while (--len >= 0 && isspace(buf[len])) { 199 buf[len] = '\0'; 200 } 201 } 202 203 return; 204 } 205 206 /** 207 * encode the given string value such that all separator characters ('/','+','|','%') 208 * in the string are repaced by their corresponding encodings (%2F","%2B","%7C", "%25") 209 */ 210 static void encodeInPlace(char value[], const int size) { 211 char buffer[size]; 212 213 struct ENCODE { 214 const char ch; 215 const char *code; 216 }; 217 218 const ENCODE encodings[] = { {'/', "%2F"}, {'+', "%2B"}, {'|', "%7C",}, {'%', "%25"} }; 219 const int nencodings = (int)sizeof(encodings) / sizeof(encodings[0]); 220 221 int inpos = 0, outpos = 0; 222 while(value[inpos] != '\0' && outpos < size - 1) { 223 // check if escaped character 224 int escchar = 0; 225 while(escchar < nencodings && encodings[escchar].ch != value[inpos]) { 226 escchar++; 227 } 228 229 if (escchar == nencodings) { 230 // non escaped character 231 buffer[outpos++] = value[inpos++]; 232 continue; 233 } 234 235 // escaped character 236 int codepos = 0; 237 #define NUM_CHARS_IN_CODE 3 238 239 if (outpos + NUM_CHARS_IN_CODE >= size) { 240 // skip last character if there is insufficient space 241 break; 242 } 243 244 while(outpos < size - 1 && codepos < NUM_CHARS_IN_CODE) { 245 buffer[outpos++] = encodings[escchar].code[codepos++]; 246 } 247 inpos++; 248 } 249 250 // copy to ouput 251 value[outpos] = '\0'; 252 while(--outpos >= 0) { 253 value[outpos] = buffer[outpos]; 254 } 255 } 256 }; 257 258 sendMsg(new LocSetXtraUserAgent(mContext)); 259 } 260 261 void LocInternalAdapter::setUlpProxy(UlpProxyBase* ulp) { 262 struct LocSetUlpProxy : public LocMsg { 263 LocAdapterBase* mAdapter; 264 UlpProxyBase* mUlp; 265 inline LocSetUlpProxy(LocAdapterBase* adapter, UlpProxyBase* ulp) : 266 LocMsg(), mAdapter(adapter), mUlp(ulp) { 267 } 268 virtual void proc() const { 269 LOC_LOGV("%s] ulp %p adapter %p", __func__, 270 mUlp, mAdapter); 271 mAdapter->setUlpProxy(mUlp); 272 } 273 }; 274 275 sendMsg(new LocSetUlpProxy(mLocEngAdapter, ulp)); 276 } 277 278 void LocEngAdapter::setUlpProxy(UlpProxyBase* ulp) 279 { 280 if (ulp == mUlp) { 281 //This takes care of the case when double initalization happens 282 //and we get the same object back for UlpProxyBase . Do nothing 283 return; 284 } 285 286 LOC_LOGV("%s] %p", __func__, ulp); 287 if (NULL == ulp) { 288 LOC_LOGE("%s:%d]: ulp pointer is NULL", __func__, __LINE__); 289 ulp = new UlpProxyBase(); 290 } 291 292 if (LOC_POSITION_MODE_INVALID != mUlp->mPosMode.mode) { 293 // need to send this mode and start msg to ULP 294 ulp->sendFixMode(mUlp->mPosMode); 295 } 296 297 if(mUlp->mFixSet) { 298 ulp->sendStartFix(); 299 } 300 301 delete mUlp; 302 mUlp = ulp; 303 } 304 305 int LocEngAdapter::setGpsLockMsg(LOC_GPS_LOCK_MASK lockMask) 306 { 307 struct LocEngAdapterGpsLock : public LocMsg { 308 LocEngAdapter* mAdapter; 309 LOC_GPS_LOCK_MASK mLockMask; 310 inline LocEngAdapterGpsLock(LocEngAdapter* adapter, LOC_GPS_LOCK_MASK lockMask) : 311 LocMsg(), mAdapter(adapter), mLockMask(lockMask) 312 { 313 locallog(); 314 } 315 inline virtual void proc() const { 316 mAdapter->setGpsLock(mLockMask); 317 } 318 inline void locallog() const { 319 LOC_LOGV("LocEngAdapterGpsLock - mLockMask: %x", mLockMask); 320 } 321 inline virtual void log() const { 322 locallog(); 323 } 324 }; 325 sendMsg(new LocEngAdapterGpsLock(this, lockMask)); 326 return 0; 327 } 328 329 void LocEngAdapter::requestPowerVote() 330 { 331 if (getPowerVoteRight()) { 332 /* Power voting without engine lock: 333 * 101: vote down, 102-104 - vote up 334 * These codes are used not to confuse with actual engine lock 335 * functionality, that can't be used in SSR scenario, as it 336 * conflicts with initialization sequence. 337 */ 338 bool powerUp = getPowerVote(); 339 LOC_LOGV("LocEngAdapterVotePower - Vote Power: %d", (int)powerUp); 340 setGpsLock(powerUp ? 103 : 101); 341 } 342 } 343 344 void LocInternalAdapter::reportPosition(UlpLocation &location, 345 GpsLocationExtended &locationExtended, 346 void* locationExt, 347 enum loc_sess_status status, 348 LocPosTechMask loc_technology_mask) 349 { 350 sendMsg(new LocEngReportPosition(mLocEngAdapter, 351 location, 352 locationExtended, 353 locationExt, 354 status, 355 loc_technology_mask)); 356 } 357 358 359 void LocEngAdapter::reportPosition(UlpLocation &location, 360 GpsLocationExtended &locationExtended, 361 void* locationExt, 362 enum loc_sess_status status, 363 LocPosTechMask loc_technology_mask) 364 { 365 if (! mUlp->reportPosition(location, 366 locationExtended, 367 locationExt, 368 status, 369 loc_technology_mask )) { 370 mInternalAdapter->reportPosition(location, 371 locationExtended, 372 locationExt, 373 status, 374 loc_technology_mask); 375 } 376 } 377 378 void LocInternalAdapter::reportSv(GnssSvStatus &svStatus, 379 GpsLocationExtended &locationExtended, 380 void* svExt){ 381 sendMsg(new LocEngReportSv(mLocEngAdapter, svStatus, 382 locationExtended, svExt)); 383 } 384 385 void LocEngAdapter::reportSv(GnssSvStatus &svStatus, 386 GpsLocationExtended &locationExtended, 387 void* svExt) 388 { 389 390 // We want to send SV info to ULP to help it in determining GNSS 391 // signal strength ULP will forward the SV reports to HAL without 392 // any modifications 393 if (! mUlp->reportSv(svStatus, locationExtended, svExt)) { 394 mInternalAdapter->reportSv(svStatus, locationExtended, svExt); 395 } 396 } 397 398 399 void LocEngAdapter::reportSvMeasurement(GnssSvMeasurementSet &svMeasurementSet) 400 { 401 // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary. 402 if (! mUlp->reportSvMeasurement(svMeasurementSet)) { 403 //Send to Internal Adapter later if needed by LA 404 } 405 } 406 407 void LocEngAdapter::reportSvPolynomial(GnssSvPolynomial &svPolynomial) 408 { 409 // We send SvMeasurementSet to AmtProxy/ULPProxy to be forwarded as necessary. 410 if (! mUlp->reportSvPolynomial(svPolynomial)) { 411 //Send to Internal Adapter later if needed by LA 412 } 413 } 414 415 void LocEngAdapter::setInSession(bool inSession) 416 { 417 mNavigating = inSession; 418 mLocApi->setInSession(inSession); 419 if (!mNavigating) { 420 mFixCriteria.mode = LOC_POSITION_MODE_INVALID; 421 } 422 } 423 424 void LocInternalAdapter::reportStatus(GpsStatusValue status) 425 { 426 sendMsg(new LocEngReportStatus(mLocEngAdapter, status)); 427 } 428 429 void LocEngAdapter::reportStatus(GpsStatusValue status) 430 { 431 if (!mUlp->reportStatus(status)) { 432 mInternalAdapter->reportStatus(status); 433 } 434 } 435 436 void LocInternalAdapter::reportNmea(const char* nmea, int length) 437 { 438 sendMsg(new LocEngReportNmea(mLocEngAdapter->getOwner(), nmea, length)); 439 } 440 441 inline void LocEngAdapter::reportNmea(const char* nmea, int length) 442 { 443 if (!mUlp->reportNmea(nmea, length)) { 444 //Report it to HAL 445 mInternalAdapter->reportNmea(nmea, length); 446 } 447 } 448 449 inline 450 bool LocEngAdapter::reportXtraServer(const char* url1, 451 const char* url2, 452 const char* url3, 453 const int maxlength) 454 { 455 if (mSupportsAgpsRequests) { 456 sendMsg(new LocEngReportXtraServer(mOwner, url1, 457 url2, url3, maxlength)); 458 } 459 return mSupportsAgpsRequests; 460 } 461 462 inline 463 bool LocEngAdapter::requestATL(int connHandle, AGpsType agps_type) 464 { 465 if (mSupportsAgpsRequests) { 466 sendMsg(new LocEngRequestATL(mOwner, 467 connHandle, agps_type)); 468 } 469 return mSupportsAgpsRequests; 470 } 471 472 inline 473 bool LocEngAdapter::releaseATL(int connHandle) 474 { 475 if (mSupportsAgpsRequests) { 476 sendMsg(new LocEngReleaseATL(mOwner, connHandle)); 477 } 478 return mSupportsAgpsRequests; 479 } 480 481 inline 482 bool LocEngAdapter::requestXtraData() 483 { 484 if (mSupportsAgpsRequests) { 485 sendMsg(new LocEngRequestXtra(mOwner)); 486 } 487 return mSupportsAgpsRequests; 488 } 489 490 inline 491 bool LocEngAdapter::requestTime() 492 { 493 if (mSupportsAgpsRequests) { 494 sendMsg(new LocEngRequestTime(mOwner)); 495 } 496 return mSupportsAgpsRequests; 497 } 498 499 inline 500 bool LocEngAdapter::requestNiNotify(GpsNiNotification ¬if, const void* data) 501 { 502 if (mSupportsAgpsRequests) { 503 notif.size = sizeof(notif); 504 notif.timeout = LOC_NI_NO_RESPONSE_TIME; 505 506 sendMsg(new LocEngRequestNi(mOwner, notif, data)); 507 } 508 return mSupportsAgpsRequests; 509 } 510 511 inline 512 bool LocEngAdapter::requestSuplES(int connHandle) 513 { 514 if (mSupportsAgpsRequests) 515 sendMsg(new LocEngRequestSuplEs(mOwner, connHandle)); 516 return mSupportsAgpsRequests; 517 } 518 519 inline 520 bool LocEngAdapter::reportDataCallOpened() 521 { 522 if(mSupportsAgpsRequests) 523 sendMsg(new LocEngSuplEsOpened(mOwner)); 524 return mSupportsAgpsRequests; 525 } 526 527 inline 528 bool LocEngAdapter::reportDataCallClosed() 529 { 530 if(mSupportsAgpsRequests) 531 sendMsg(new LocEngSuplEsClosed(mOwner)); 532 return mSupportsAgpsRequests; 533 } 534 535 inline 536 void LocEngAdapter::handleEngineDownEvent() 537 { 538 sendMsg(new LocEngDown(mOwner)); 539 } 540 541 inline 542 void LocEngAdapter::handleEngineUpEvent() 543 { 544 sendMsg(new LocEngUp(mOwner)); 545 } 546 547 enum loc_api_adapter_err LocEngAdapter::setTime(GpsUtcTime time, 548 int64_t timeReference, 549 int uncertainty) 550 { 551 loc_api_adapter_err result = LOC_API_ADAPTER_ERR_SUCCESS; 552 553 LOC_LOGD("%s:%d]: mSupportsTimeInjection is %d", 554 __func__, __LINE__, mSupportsTimeInjection); 555 556 if (mSupportsTimeInjection) { 557 LOC_LOGD("%s:%d]: Injecting time", __func__, __LINE__); 558 result = mLocApi->setTime(time, timeReference, uncertainty); 559 } 560 561 return result; 562 } 563 564 enum loc_api_adapter_err LocEngAdapter::setXtraVersionCheck(int check) 565 { 566 enum loc_api_adapter_err ret; 567 ENTRY_LOG(); 568 enum xtra_version_check eCheck; 569 switch (check) { 570 case 0: 571 eCheck = DISABLED; 572 break; 573 case 1: 574 eCheck = AUTO; 575 break; 576 case 2: 577 eCheck = XTRA2; 578 break; 579 case 3: 580 eCheck = XTRA3; 581 break; 582 default: 583 eCheck = DISABLED; 584 } 585 ret = mLocApi->setXtraVersionCheck(eCheck); 586 EXIT_LOG(%d, ret); 587 return ret; 588 } 589 590 void LocEngAdapter::reportGnssMeasurementData(GnssData &gnssMeasurementData) 591 { 592 sendMsg(new LocEngReportGnssMeasurement(mOwner, 593 gnssMeasurementData)); 594 } 595 596 /* 597 Set Gnss Constellation Config 598 */ 599 bool LocEngAdapter::gnssConstellationConfig() 600 { 601 LOC_LOGD("entering %s", __func__); 602 bool result = false; 603 result = mLocApi->gnssConstellationConfig(); 604 return result; 605 } 606