1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <cinttypes> 18 #include <cstddef> 19 #include <cstring> 20 21 #include "chre/core/event_loop_manager.h" 22 #include "chre/core/settings.h" 23 #include "chre/core/wifi_request_manager.h" 24 #include "chre/platform/fatal_error.h" 25 #include "chre/platform/log.h" 26 #include "chre/platform/system_time.h" 27 #include "chre/util/system/debug_dump.h" 28 #include "chre_api/chre/version.h" 29 30 namespace chre { 31 32 WifiRequestManager::WifiRequestManager() { 33 // Reserve space for at least one scan monitoring nanoapp. This ensures that 34 // the first asynchronous push_back will succeed. Future push_backs will be 35 // synchronous and failures will be returned to the client. 36 if (!mScanMonitorNanoapps.reserve(1)) { 37 FATAL_ERROR_OOM(); 38 } 39 } 40 41 void WifiRequestManager::init() { 42 mPlatformWifi.init(); 43 } 44 45 uint32_t WifiRequestManager::getCapabilities() { 46 return mPlatformWifi.getCapabilities(); 47 } 48 49 bool WifiRequestManager::configureScanMonitor(Nanoapp *nanoapp, bool enable, 50 const void *cookie) { 51 CHRE_ASSERT(nanoapp); 52 53 bool success = false; 54 uint32_t instanceId = nanoapp->getInstanceId(); 55 bool hasScanMonitorRequest = nanoappHasScanMonitorRequest(instanceId); 56 if (!mPendingScanMonitorRequests.empty()) { 57 success = addScanMonitorRequestToQueue(nanoapp, enable, cookie); 58 } else if (scanMonitorIsInRequestedState(enable, hasScanMonitorRequest)) { 59 // The scan monitor is already in the requested state. A success event can 60 // be posted immediately. 61 success = postScanMonitorAsyncResultEvent(instanceId, true /* success */, 62 enable, CHRE_ERROR_NONE, cookie); 63 } else if (scanMonitorStateTransitionIsRequired(enable, 64 hasScanMonitorRequest)) { 65 success = addScanMonitorRequestToQueue(nanoapp, enable, cookie); 66 if (success) { 67 success = mPlatformWifi.configureScanMonitor(enable); 68 if (!success) { 69 mPendingScanMonitorRequests.pop_back(); 70 LOGE("Failed to enable the scan monitor for nanoapp instance %" PRIu32, 71 instanceId); 72 } 73 } 74 } else { 75 CHRE_ASSERT_LOG(false, "Invalid scan monitor configuration"); 76 } 77 78 return success; 79 } 80 81 bool WifiRequestManager::requestRanging( 82 Nanoapp *nanoapp, const struct chreWifiRangingParams *params, 83 const void *cookie) { 84 CHRE_ASSERT(nanoapp); 85 86 bool success = false; 87 if (!mPendingRangingRequests.emplace()) { 88 LOGE("Can't issue new RTT request; pending queue full"); 89 } else { 90 PendingRangingRequest &req = mPendingRangingRequests.back(); 91 req.nanoappInstanceId = nanoapp->getInstanceId(); 92 req.cookie = cookie; 93 94 if (mPendingRangingRequests.size() == 1) { 95 // First in line; dispatch request immediately 96 if (getSettingState(Setting::LOCATION) == SettingState::DISABLED) { 97 // Treat as success but post async failure per API. 98 success = true; 99 postRangingAsyncResult(CHRE_ERROR_FUNCTION_DISABLED); 100 mPendingRangingRequests.pop_back(); 101 } else if (!mPlatformWifi.requestRanging(params)) { 102 LOGE("WiFi RTT request failed"); 103 mPendingRangingRequests.pop_back(); 104 } else { 105 success = true; 106 mRangingResponseTimeout = 107 SystemTime::getMonotonicTime() + 108 Nanoseconds(CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS); 109 } 110 } else { 111 // Dispatch request later, after prior requests finish 112 // TODO(b/65331248): use a timer to ensure the platform is meeting its 113 // contract 114 CHRE_ASSERT_LOG(SystemTime::getMonotonicTime() <= mRangingResponseTimeout, 115 "WiFi platform didn't give callback in time"); 116 success = 117 req.targetList.copy_array(params->targetList, params->targetListLen); 118 if (!success) { 119 LOG_OOM(); 120 mPendingRangingRequests.pop_back(); 121 } 122 } 123 } 124 125 return success; 126 } 127 128 bool WifiRequestManager::requestScan(Nanoapp *nanoapp, 129 const struct chreWifiScanParams *params, 130 const void *cookie) { 131 CHRE_ASSERT(nanoapp); 132 133 // TODO(b/65331248): replace with a timer to actively check response timeout 134 bool timedOut = 135 (mScanRequestingNanoappInstanceId.has_value() && 136 mLastScanRequestTime + Nanoseconds(CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS) < 137 SystemTime::getMonotonicTime()); 138 if (timedOut) { 139 LOGE("Scan request async response timed out"); 140 mScanRequestingNanoappInstanceId.reset(); 141 } 142 143 // Handle compatibility with nanoapps compiled against API v1.1, which doesn't 144 // include the radioChainPref parameter in chreWifiScanParams 145 struct chreWifiScanParams paramsCompat; 146 if (nanoapp->getTargetApiVersion() < CHRE_API_VERSION_1_2) { 147 memcpy(¶msCompat, params, offsetof(chreWifiScanParams, radioChainPref)); 148 paramsCompat.radioChainPref = CHRE_WIFI_RADIO_CHAIN_PREF_DEFAULT; 149 params = ¶msCompat; 150 } 151 152 bool success = false; 153 if (mScanRequestingNanoappInstanceId.has_value()) { 154 LOGE("Active wifi scan request made while a request is in flight"); 155 } else { 156 success = mPlatformWifi.requestScan(params); 157 if (!success) { 158 LOGE("Wifi scan request failed"); 159 } else { 160 mScanRequestingNanoappInstanceId = nanoapp->getInstanceId(); 161 mScanRequestingNanoappCookie = cookie; 162 mLastScanRequestTime = SystemTime::getMonotonicTime(); 163 } 164 } 165 166 if (success) { 167 addWifiScanRequestLog(nanoapp->getInstanceId(), params); 168 } 169 170 return success; 171 } 172 173 void WifiRequestManager::handleScanMonitorStateChange(bool enabled, 174 uint8_t errorCode) { 175 struct CallbackState { 176 bool enabled; 177 uint8_t errorCode; 178 }; 179 180 auto *cbState = memoryAlloc<CallbackState>(); 181 if (cbState == nullptr) { 182 LOG_OOM(); 183 } else { 184 cbState->enabled = enabled; 185 cbState->errorCode = errorCode; 186 187 auto callback = [](uint16_t /* eventType */, void *eventData) { 188 auto *state = static_cast<CallbackState *>(eventData); 189 EventLoopManagerSingleton::get() 190 ->getWifiRequestManager() 191 .handleScanMonitorStateChangeSync(state->enabled, state->errorCode); 192 memoryFree(state); 193 }; 194 195 EventLoopManagerSingleton::get()->deferCallback( 196 SystemCallbackType::WifiScanMonitorStateChange, cbState, callback); 197 } 198 } 199 200 void WifiRequestManager::handleScanResponse(bool pending, uint8_t errorCode) { 201 struct CallbackState { 202 bool pending; 203 uint8_t errorCode; 204 }; 205 206 auto *cbState = memoryAlloc<CallbackState>(); 207 if (cbState == nullptr) { 208 LOG_OOM(); 209 } else { 210 cbState->pending = pending; 211 cbState->errorCode = errorCode; 212 213 auto callback = [](uint16_t /* eventType */, void *eventData) { 214 auto *state = static_cast<CallbackState *>(eventData); 215 EventLoopManagerSingleton::get() 216 ->getWifiRequestManager() 217 .handleScanResponseSync(state->pending, state->errorCode); 218 memoryFree(state); 219 }; 220 221 EventLoopManagerSingleton::get()->deferCallback( 222 SystemCallbackType::WifiRequestScanResponse, cbState, callback); 223 } 224 } 225 226 void WifiRequestManager::handleRangingEvent( 227 uint8_t errorCode, struct chreWifiRangingEvent *event) { 228 // Use two different callbacks to avoid needing a temporary allocation to 229 // carry the error code into the event loop context 230 if (errorCode != CHRE_ERROR_NONE) { 231 // Enables passing the error code through the event data pointer to avoid 232 // allocating memory 233 union NestedErrorCode { 234 void *eventData; 235 uint8_t errorCode; 236 }; 237 238 auto errorCb = [](uint16_t /* eventType */, void *eventData) { 239 NestedErrorCode cbErrorCode; 240 cbErrorCode.eventData = eventData; 241 EventLoopManagerSingleton::get() 242 ->getWifiRequestManager() 243 .handleRangingEventSync(cbErrorCode.errorCode, nullptr); 244 }; 245 246 NestedErrorCode error = {}; 247 error.errorCode = errorCode; 248 EventLoopManagerSingleton::get()->deferCallback( 249 SystemCallbackType::WifiHandleFailedRanging, error.eventData, errorCb); 250 } else { 251 auto successCb = [](uint16_t /* eventType */, void *eventData) { 252 auto *rttEvent = static_cast<struct chreWifiRangingEvent *>(eventData); 253 EventLoopManagerSingleton::get() 254 ->getWifiRequestManager() 255 .handleRangingEventSync(CHRE_ERROR_NONE, rttEvent); 256 }; 257 258 EventLoopManagerSingleton::get()->deferCallback( 259 SystemCallbackType::WifiHandleRangingEvent, event, successCb); 260 } 261 } 262 263 void WifiRequestManager::handleScanEvent(chreWifiScanEvent *event) { 264 auto callback = [](uint16_t eventType, void *eventData) { 265 chreWifiScanEvent *scanEvent = static_cast<chreWifiScanEvent *>(eventData); 266 EventLoopManagerSingleton::get() 267 ->getWifiRequestManager() 268 .postScanEventFatal(scanEvent); 269 }; 270 271 EventLoopManagerSingleton::get()->deferCallback( 272 SystemCallbackType::WifiHandleScanEvent, event, callback); 273 } 274 275 void WifiRequestManager::logStateToBuffer(DebugDumpWrapper &debugDump) const { 276 debugDump.print("\nWifi: scan monitor %s\n", 277 scanMonitorIsEnabled() ? "enabled" : "disabled"); 278 279 if (scanMonitorIsEnabled()) { 280 debugDump.print(" Wifi scan monitor enabled nanoapps:\n"); 281 for (const auto &instanceId : mScanMonitorNanoapps) { 282 debugDump.print(" nappId=%" PRIu32 "\n", instanceId); 283 } 284 } 285 286 if (mScanRequestingNanoappInstanceId.has_value()) { 287 debugDump.print(" Wifi request pending nanoappId=%" PRIu32 "\n", 288 mScanRequestingNanoappInstanceId.value()); 289 } 290 291 if (!mPendingScanMonitorRequests.empty()) { 292 debugDump.print(" Wifi transition queue:\n"); 293 for (const auto &transition : mPendingScanMonitorRequests) { 294 debugDump.print(" enable=%s nappId=%" PRIu32 "\n", 295 transition.enable ? "true" : "false", 296 transition.nanoappInstanceId); 297 } 298 } 299 300 debugDump.print(" Last %zu wifi scan requests:\n", 301 mWifiScanRequestLogs.size()); 302 static_assert(kNumWifiRequestLogs <= INT8_MAX, 303 "kNumWifiRequestLogs must be <= INT8_MAX"); 304 for (int8_t i = static_cast<int8_t>(mWifiScanRequestLogs.size()) - 1; i >= 0; 305 i--) { 306 const auto &log = mWifiScanRequestLogs[static_cast<size_t>(i)]; 307 debugDump.print(" ts=%" PRIu64 " nappId=%" PRIu32 " scanType=%" PRIu8 308 " maxScanAge(ms)=%" PRIu64 "\n", 309 log.timestamp.toRawNanoseconds(), log.instanceId, 310 log.scanType, log.maxScanAgeMs.getMilliseconds()); 311 } 312 } 313 314 bool WifiRequestManager::scanMonitorIsEnabled() const { 315 return !mScanMonitorNanoapps.empty(); 316 } 317 318 bool WifiRequestManager::nanoappHasScanMonitorRequest( 319 uint32_t instanceId, size_t *nanoappIndex) const { 320 size_t index = mScanMonitorNanoapps.find(instanceId); 321 bool hasScanMonitorRequest = (index != mScanMonitorNanoapps.size()); 322 if (hasScanMonitorRequest && nanoappIndex != nullptr) { 323 *nanoappIndex = index; 324 } 325 326 return hasScanMonitorRequest; 327 } 328 329 bool WifiRequestManager::scanMonitorIsInRequestedState( 330 bool requestedState, bool nanoappHasRequest) const { 331 return (requestedState == scanMonitorIsEnabled() || 332 (!requestedState && 333 (!nanoappHasRequest || mScanMonitorNanoapps.size() > 1))); 334 } 335 336 bool WifiRequestManager::scanMonitorStateTransitionIsRequired( 337 bool requestedState, bool nanoappHasRequest) const { 338 return ((requestedState && mScanMonitorNanoapps.empty()) || 339 (!requestedState && nanoappHasRequest && 340 mScanMonitorNanoapps.size() == 1)); 341 } 342 343 bool WifiRequestManager::addScanMonitorRequestToQueue(Nanoapp *nanoapp, 344 bool enable, 345 const void *cookie) { 346 PendingScanMonitorRequest scanMonitorStateTransition; 347 scanMonitorStateTransition.nanoappInstanceId = nanoapp->getInstanceId(); 348 scanMonitorStateTransition.cookie = cookie; 349 scanMonitorStateTransition.enable = enable; 350 351 bool success = mPendingScanMonitorRequests.push(scanMonitorStateTransition); 352 if (!success) { 353 LOGW("Too many scan monitor state transitions"); 354 } 355 356 return success; 357 } 358 359 bool WifiRequestManager::updateNanoappScanMonitoringList(bool enable, 360 uint32_t instanceId) { 361 bool success = true; 362 Nanoapp *nanoapp = 363 EventLoopManagerSingleton::get()->getEventLoop().findNanoappByInstanceId( 364 instanceId); 365 if (nanoapp == nullptr) { 366 LOGW("Failed to update scan monitoring list for non-existent nanoapp"); 367 } else { 368 size_t nanoappIndex; 369 bool hasExistingRequest = 370 nanoappHasScanMonitorRequest(instanceId, &nanoappIndex); 371 if (enable) { 372 if (!hasExistingRequest) { 373 // The scan monitor was successfully enabled for this nanoapp and 374 // there is no existing request. Add it to the list of scan monitoring 375 // nanoapps. 376 success = mScanMonitorNanoapps.push_back(instanceId); 377 if (!success) { 378 LOG_OOM(); 379 } else { 380 nanoapp->registerForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT); 381 } 382 } 383 } else if (hasExistingRequest) { 384 // The scan monitor was successfully disabled for a previously enabled 385 // nanoapp. Remove it from the list of scan monitoring nanoapps. 386 mScanMonitorNanoapps.erase(nanoappIndex); 387 nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT); 388 } // else disabling an inactive request, treat as success per the CHRE API. 389 } 390 391 return success; 392 } 393 394 bool WifiRequestManager::postScanMonitorAsyncResultEvent( 395 uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode, 396 const void *cookie) { 397 // Allocate and post an event to the nanoapp requesting wifi. 398 bool eventPosted = false; 399 if (!success || updateNanoappScanMonitoringList(enable, nanoappInstanceId)) { 400 chreAsyncResult *event = memoryAlloc<chreAsyncResult>(); 401 if (event == nullptr) { 402 LOG_OOM(); 403 } else { 404 event->requestType = CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR; 405 event->success = success; 406 event->errorCode = errorCode; 407 event->reserved = 0; 408 event->cookie = cookie; 409 410 // Post the event. 411 eventPosted = 412 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie( 413 CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback, 414 nanoappInstanceId); 415 if (!eventPosted) { 416 memoryFree(event); 417 } 418 } 419 } 420 421 return eventPosted; 422 } 423 424 void WifiRequestManager::postScanMonitorAsyncResultEventFatal( 425 uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode, 426 const void *cookie) { 427 if (!postScanMonitorAsyncResultEvent(nanoappInstanceId, success, enable, 428 errorCode, cookie)) { 429 FATAL_ERROR("Failed to send WiFi scan monitor async result event"); 430 } 431 } 432 433 bool WifiRequestManager::postScanRequestAsyncResultEvent( 434 uint32_t nanoappInstanceId, bool success, uint8_t errorCode, 435 const void *cookie) { 436 bool eventPosted = false; 437 chreAsyncResult *event = memoryAlloc<chreAsyncResult>(); 438 if (event == nullptr) { 439 LOG_OOM(); 440 } else { 441 event->requestType = CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN; 442 event->success = success; 443 event->errorCode = errorCode; 444 event->reserved = 0; 445 event->cookie = cookie; 446 447 // Post the event. 448 eventPosted = 449 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie( 450 CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback, 451 nanoappInstanceId); 452 } 453 454 return eventPosted; 455 } 456 457 void WifiRequestManager::postScanRequestAsyncResultEventFatal( 458 uint32_t nanoappInstanceId, bool success, uint8_t errorCode, 459 const void *cookie) { 460 if (!postScanRequestAsyncResultEvent(nanoappInstanceId, success, errorCode, 461 cookie)) { 462 FATAL_ERROR("Failed to send WiFi scan request async result event"); 463 } 464 } 465 466 void WifiRequestManager::postScanEventFatal(chreWifiScanEvent *event) { 467 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie( 468 CHRE_EVENT_WIFI_SCAN_RESULT, event, freeWifiScanEventCallback); 469 } 470 471 void WifiRequestManager::handleScanMonitorStateChangeSync(bool enabled, 472 uint8_t errorCode) { 473 // Success is defined as having no errors ... in life ༼ つ ◕_◕ ༽つ 474 bool success = (errorCode == CHRE_ERROR_NONE); 475 476 // TODO(b/62904616): re-enable this assertion 477 // CHRE_ASSERT_LOG(!mScanMonitorStateTransitions.empty(), 478 // "handleScanMonitorStateChangeSync called with no 479 // transitions"); 480 if (mPendingScanMonitorRequests.empty()) { 481 LOGE( 482 "WiFi PAL error: handleScanMonitorStateChangeSync called with no " 483 "transitions (enabled %d errorCode %" PRIu8 ")", 484 enabled, errorCode); 485 } 486 487 // Always check the front of the queue. 488 if (!mPendingScanMonitorRequests.empty()) { 489 const auto &stateTransition = mPendingScanMonitorRequests.front(); 490 success &= (stateTransition.enable == enabled); 491 postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId, 492 success, stateTransition.enable, 493 errorCode, stateTransition.cookie); 494 mPendingScanMonitorRequests.pop(); 495 } 496 497 while (!mPendingScanMonitorRequests.empty()) { 498 const auto &stateTransition = mPendingScanMonitorRequests.front(); 499 bool hasScanMonitorRequest = 500 nanoappHasScanMonitorRequest(stateTransition.nanoappInstanceId); 501 if (scanMonitorIsInRequestedState(stateTransition.enable, 502 hasScanMonitorRequest)) { 503 // We are already in the target state so just post an event indicating 504 // success 505 postScanMonitorAsyncResultEventFatal( 506 stateTransition.nanoappInstanceId, true /* success */, 507 stateTransition.enable, CHRE_ERROR_NONE, stateTransition.cookie); 508 } else if (scanMonitorStateTransitionIsRequired(stateTransition.enable, 509 hasScanMonitorRequest)) { 510 if (mPlatformWifi.configureScanMonitor(stateTransition.enable)) { 511 break; 512 } else { 513 postScanMonitorAsyncResultEventFatal( 514 stateTransition.nanoappInstanceId, false /* success */, 515 stateTransition.enable, CHRE_ERROR, stateTransition.cookie); 516 } 517 } else { 518 CHRE_ASSERT_LOG(false, "Invalid scan monitor state"); 519 break; 520 } 521 522 mPendingScanMonitorRequests.pop(); 523 } 524 } 525 526 void WifiRequestManager::handleScanResponseSync(bool pending, 527 uint8_t errorCode) { 528 // TODO(b/65206783): re-enable this assertion 529 // CHRE_ASSERT_LOG(mScanRequestingNanoappInstanceId.has_value(), 530 // "handleScanResponseSync called with no outstanding 531 // request"); 532 if (!mScanRequestingNanoappInstanceId.has_value()) { 533 LOGE("handleScanResponseSync called with no outstanding request"); 534 } 535 536 // TODO: raise this to CHRE_ASSERT_LOG 537 if (!pending && errorCode == CHRE_ERROR_NONE) { 538 LOGE("Invalid wifi scan response"); 539 errorCode = CHRE_ERROR; 540 } 541 542 if (mScanRequestingNanoappInstanceId.has_value()) { 543 bool success = (pending && errorCode == CHRE_ERROR_NONE); 544 if (!success) { 545 LOGW("Wifi scan request failed: pending %d, errorCode %" PRIu8, pending, 546 errorCode); 547 } 548 postScanRequestAsyncResultEventFatal(*mScanRequestingNanoappInstanceId, 549 success, errorCode, 550 mScanRequestingNanoappCookie); 551 552 // Set a flag to indicate that results may be pending. 553 mScanRequestResultsArePending = pending; 554 555 if (pending) { 556 Nanoapp *nanoapp = 557 EventLoopManagerSingleton::get() 558 ->getEventLoop() 559 .findNanoappByInstanceId(*mScanRequestingNanoappInstanceId); 560 if (nanoapp == nullptr) { 561 LOGW("Received WiFi scan response for unknown nanoapp"); 562 } else { 563 nanoapp->registerForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT); 564 } 565 } else { 566 // If the scan results are not pending, clear the nanoapp instance ID. 567 // Otherwise, wait for the results to be delivered and then clear the 568 // instance ID. 569 mScanRequestingNanoappInstanceId.reset(); 570 } 571 } 572 } 573 574 bool WifiRequestManager::postRangingAsyncResult(uint8_t errorCode) { 575 bool eventPosted = false; 576 577 if (mPendingRangingRequests.empty()) { 578 LOGE("Unexpected ranging event callback"); 579 } else { 580 auto *event = memoryAlloc<struct chreAsyncResult>(); 581 if (event == nullptr) { 582 LOG_OOM(); 583 } else { 584 const PendingRangingRequest &req = mPendingRangingRequests.front(); 585 586 event->requestType = CHRE_WIFI_REQUEST_TYPE_RANGING; 587 event->success = (errorCode == CHRE_ERROR_NONE); 588 event->errorCode = errorCode; 589 event->reserved = 0; 590 event->cookie = req.cookie; 591 592 eventPosted = 593 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie( 594 CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback, 595 req.nanoappInstanceId); 596 if (!eventPosted) { 597 memoryFree(event); 598 } 599 } 600 } 601 602 return eventPosted; 603 } 604 605 bool WifiRequestManager::dispatchQueuedRangingRequest() { 606 const PendingRangingRequest &req = mPendingRangingRequests.front(); 607 struct chreWifiRangingParams params = {}; 608 params.targetListLen = static_cast<uint8_t>(req.targetList.size()); 609 params.targetList = req.targetList.data(); 610 611 bool success = false; 612 if (getSettingState(Setting::LOCATION) == SettingState::DISABLED) { 613 postRangingAsyncResult(CHRE_ERROR_FUNCTION_DISABLED); 614 mPendingRangingRequests.pop(); 615 } else if (!mPlatformWifi.requestRanging(¶ms)) { 616 LOGE("Failed to issue queued ranging result"); 617 postRangingAsyncResult(CHRE_ERROR); 618 mPendingRangingRequests.pop(); 619 } else { 620 success = true; 621 mRangingResponseTimeout = SystemTime::getMonotonicTime() + 622 Nanoseconds(CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS); 623 } 624 625 return success; 626 } 627 628 void WifiRequestManager::handleRangingEventSync( 629 uint8_t errorCode, struct chreWifiRangingEvent *event) { 630 if (getSettingState(Setting::LOCATION) == SettingState::DISABLED) { 631 errorCode = CHRE_ERROR_FUNCTION_DISABLED; 632 } 633 634 if (postRangingAsyncResult(errorCode)) { 635 if (errorCode != CHRE_ERROR_NONE) { 636 LOGW("RTT ranging failed with error %d", errorCode); 637 if (event != nullptr) { 638 freeWifiRangingEventCallback(CHRE_EVENT_WIFI_RANGING_RESULT, event); 639 } 640 } else { 641 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie( 642 CHRE_EVENT_WIFI_RANGING_RESULT, event, freeWifiRangingEventCallback, 643 mPendingRangingRequests.front().nanoappInstanceId); 644 } 645 mPendingRangingRequests.pop(); 646 } 647 648 // If we have any pending requests, try issuing them to the platform until the 649 // first one succeeds 650 while (!mPendingRangingRequests.empty() && !dispatchQueuedRangingRequest()) 651 ; 652 } 653 654 void WifiRequestManager::handleFreeWifiScanEvent(chreWifiScanEvent *scanEvent) { 655 if (mScanRequestResultsArePending) { 656 // Reset the event distribution logic once an entire scan event has been 657 // received and processed by the nanoapp requesting the scan event. 658 mScanEventResultCountAccumulator += scanEvent->resultCount; 659 if (mScanEventResultCountAccumulator >= scanEvent->resultTotal) { 660 mScanEventResultCountAccumulator = 0; 661 mScanRequestResultsArePending = false; 662 } 663 664 if (!mScanRequestResultsArePending && 665 mScanRequestingNanoappInstanceId.has_value()) { 666 Nanoapp *nanoapp = 667 EventLoopManagerSingleton::get() 668 ->getEventLoop() 669 .findNanoappByInstanceId(*mScanRequestingNanoappInstanceId); 670 if (nanoapp == nullptr) { 671 LOGW("Attempted to unsubscribe unknown nanoapp from WiFi scan events"); 672 } else if (!nanoappHasScanMonitorRequest( 673 *mScanRequestingNanoappInstanceId)) { 674 nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT); 675 } 676 677 mScanRequestingNanoappInstanceId.reset(); 678 } 679 } 680 681 mPlatformWifi.releaseScanEvent(scanEvent); 682 } 683 684 void WifiRequestManager::addWifiScanRequestLog( 685 uint32_t nanoappInstanceId, const chreWifiScanParams *params) { 686 mWifiScanRequestLogs.kick_push( 687 WifiScanRequestLog(SystemTime::getMonotonicTime(), nanoappInstanceId, 688 static_cast<chreWifiScanType>(params->scanType), 689 static_cast<Milliseconds>(params->maxScanAgeMs))); 690 } 691 692 void WifiRequestManager::freeWifiScanEventCallback(uint16_t eventType, 693 void *eventData) { 694 chreWifiScanEvent *scanEvent = static_cast<chreWifiScanEvent *>(eventData); 695 EventLoopManagerSingleton::get() 696 ->getWifiRequestManager() 697 .handleFreeWifiScanEvent(scanEvent); 698 } 699 700 void WifiRequestManager::freeWifiRangingEventCallback(uint16_t eventType, 701 void *eventData) { 702 auto *event = static_cast<struct chreWifiRangingEvent *>(eventData); 703 EventLoopManagerSingleton::get() 704 ->getWifiRequestManager() 705 .mPlatformWifi.releaseRangingEvent(event); 706 } 707 708 } // namespace chre 709