Home | History | Annotate | Download | only in core
      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(&paramsCompat, params, offsetof(chreWifiScanParams, radioChainPref));
    141     paramsCompat.radioChainPref = CHRE_WIFI_RADIO_CHAIN_PREF_DEFAULT;
    142     params = &paramsCompat;
    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(&params);
    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