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