• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
WifiRequestManager()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 
init()40 void WifiRequestManager::init() {
41   mPlatformWifi.init();
42 }
43 
getCapabilities()44 uint32_t WifiRequestManager::getCapabilities() {
45   return mPlatformWifi.getCapabilities();
46 }
47 
configureScanMonitor(Nanoapp * nanoapp,bool enable,const void * cookie)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 
requestRanging(Nanoapp * nanoapp,const struct chreWifiRangingParams * params,const void * cookie)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         LOG_OOM();
113         mPendingRangingRequests.pop_back();
114       }
115     }
116   }
117 
118   return success;
119 }
120 
requestScan(Nanoapp * nanoapp,const struct chreWifiScanParams * params,const void * cookie)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 
handleScanMonitorStateChange(bool enabled,uint8_t errorCode)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     LOG_OOM();
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 
handleScanResponse(bool pending,uint8_t errorCode)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     LOG_OOM();
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 
handleRangingEvent(uint8_t errorCode,struct chreWifiRangingEvent * event)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 
handleScanEvent(chreWifiScanEvent * event)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 
logStateToBuffer(char * buffer,size_t * bufferPos,size_t bufferSize) const260 void WifiRequestManager::logStateToBuffer(char *buffer, size_t *bufferPos,
261                                           size_t bufferSize) const {
262   debugDumpPrint(buffer, bufferPos, bufferSize,
263                  "\nWifi: scan monitor %s\n",
264                  scanMonitorIsEnabled() ? "enabled" : "disabled");
265   debugDumpPrint(buffer, bufferPos, bufferSize,
266                  " Wifi scan monitor enabled nanoapps:\n");
267   for (const auto& instanceId : mScanMonitorNanoapps) {
268     debugDumpPrint(buffer, bufferPos, bufferSize,
269                    "  nanoappId=%" PRIu32 "\n", instanceId);
270   }
271 
272   if (mScanRequestingNanoappInstanceId.has_value()) {
273     debugDumpPrint(buffer, bufferPos, bufferSize,
274                    " Wifi request pending nanoappId=%" PRIu32 "\n",
275                    mScanRequestingNanoappInstanceId.value());
276   }
277 
278   debugDumpPrint(buffer, bufferPos, bufferSize,
279                  " Wifi transition queue:\n");
280   for (const auto& transition : mPendingScanMonitorRequests) {
281     debugDumpPrint(buffer, bufferPos, bufferSize,
282                    "  enable=%s nanoappId=%" PRIu32 "\n",
283                    transition.enable ? "true" : "false",
284                    transition.nanoappInstanceId);
285   }
286 }
287 
scanMonitorIsEnabled() const288 bool WifiRequestManager::scanMonitorIsEnabled() const {
289   return !mScanMonitorNanoapps.empty();
290 }
291 
nanoappHasScanMonitorRequest(uint32_t instanceId,size_t * nanoappIndex) const292 bool WifiRequestManager::nanoappHasScanMonitorRequest(
293     uint32_t instanceId, size_t *nanoappIndex) const {
294   size_t index = mScanMonitorNanoapps.find(instanceId);
295   bool hasScanMonitorRequest = (index != mScanMonitorNanoapps.size());
296   if (hasScanMonitorRequest && nanoappIndex != nullptr) {
297     *nanoappIndex = index;
298   }
299 
300   return hasScanMonitorRequest;
301 }
302 
scanMonitorIsInRequestedState(bool requestedState,bool nanoappHasRequest) const303 bool WifiRequestManager::scanMonitorIsInRequestedState(
304     bool requestedState, bool nanoappHasRequest) const {
305   return (requestedState == scanMonitorIsEnabled() || (!requestedState
306       && (!nanoappHasRequest || mScanMonitorNanoapps.size() > 1)));
307 }
308 
scanMonitorStateTransitionIsRequired(bool requestedState,bool nanoappHasRequest) const309 bool WifiRequestManager::scanMonitorStateTransitionIsRequired(
310     bool requestedState, bool nanoappHasRequest) const {
311   return ((requestedState && mScanMonitorNanoapps.empty())
312       || (!requestedState && nanoappHasRequest
313               && mScanMonitorNanoapps.size() == 1));
314 }
315 
addScanMonitorRequestToQueue(Nanoapp * nanoapp,bool enable,const void * cookie)316 bool WifiRequestManager::addScanMonitorRequestToQueue(Nanoapp *nanoapp,
317                                                       bool enable,
318                                                       const void *cookie) {
319   PendingScanMonitorRequest scanMonitorStateTransition;
320   scanMonitorStateTransition.nanoappInstanceId = nanoapp->getInstanceId();
321   scanMonitorStateTransition.cookie = cookie;
322   scanMonitorStateTransition.enable = enable;
323 
324   bool success = mPendingScanMonitorRequests.push(scanMonitorStateTransition);
325   if (!success) {
326     LOGW("Too many scan monitor state transitions");
327   }
328 
329   return success;
330 }
331 
updateNanoappScanMonitoringList(bool enable,uint32_t instanceId)332 bool WifiRequestManager::updateNanoappScanMonitoringList(bool enable,
333                                                          uint32_t instanceId) {
334   bool success = true;
335   Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
336       .findNanoappByInstanceId(instanceId);
337   if (nanoapp == nullptr) {
338     LOGW("Failed to update scan monitoring list for non-existent nanoapp");
339   } else {
340     size_t nanoappIndex;
341     bool hasExistingRequest = nanoappHasScanMonitorRequest(instanceId,
342                                                            &nanoappIndex);
343     if (enable) {
344       if (!hasExistingRequest) {
345         // The scan monitor was successfully enabled for this nanoapp and
346         // there is no existing request. Add it to the list of scan monitoring
347         // nanoapps.
348         success = mScanMonitorNanoapps.push_back(instanceId);
349         if (!success) {
350           LOG_OOM();
351         } else {
352           nanoapp->registerForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
353         }
354       }
355     } else if (hasExistingRequest) {
356       // The scan monitor was successfully disabled for a previously enabled
357       // nanoapp. Remove it from the list of scan monitoring nanoapps.
358       mScanMonitorNanoapps.erase(nanoappIndex);
359       nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
360     } // else disabling an inactive request, treat as success per the CHRE API.
361   }
362 
363   return success;
364 }
365 
postScanMonitorAsyncResultEvent(uint32_t nanoappInstanceId,bool success,bool enable,uint8_t errorCode,const void * cookie)366 bool WifiRequestManager::postScanMonitorAsyncResultEvent(
367     uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
368     const void *cookie) {
369   // Allocate and post an event to the nanoapp requesting wifi.
370   bool eventPosted = false;
371   if (!success || updateNanoappScanMonitoringList(enable, nanoappInstanceId)) {
372     chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
373     if (event == nullptr) {
374       LOG_OOM();
375     } else {
376       event->requestType = CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR;
377       event->success = success;
378       event->errorCode = errorCode;
379       event->reserved = 0;
380       event->cookie = cookie;
381 
382       // Post the event.
383       eventPosted = EventLoopManagerSingleton::get()->getEventLoop()
384           .postEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
385                      kSystemInstanceId, nanoappInstanceId);
386       if (!eventPosted) {
387         memoryFree(event);
388       }
389     }
390   }
391 
392   return eventPosted;
393 }
394 
postScanMonitorAsyncResultEventFatal(uint32_t nanoappInstanceId,bool success,bool enable,uint8_t errorCode,const void * cookie)395 void WifiRequestManager::postScanMonitorAsyncResultEventFatal(
396     uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
397     const void *cookie) {
398   if (!postScanMonitorAsyncResultEvent(nanoappInstanceId, success, enable,
399                                        errorCode, cookie)) {
400     FATAL_ERROR("Failed to send WiFi scan monitor async result event");
401   }
402 }
403 
postScanRequestAsyncResultEvent(uint32_t nanoappInstanceId,bool success,uint8_t errorCode,const void * cookie)404 bool WifiRequestManager::postScanRequestAsyncResultEvent(
405     uint32_t nanoappInstanceId, bool success, uint8_t errorCode,
406     const void *cookie) {
407   bool eventPosted = false;
408   chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
409   if (event == nullptr) {
410     LOG_OOM();
411   } else {
412     event->requestType = CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN;
413     event->success = success;
414     event->errorCode = errorCode;
415     event->reserved = 0;
416     event->cookie = cookie;
417 
418     // Post the event.
419     eventPosted = EventLoopManagerSingleton::get()->getEventLoop()
420         .postEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
421                    kSystemInstanceId, nanoappInstanceId);
422   }
423 
424   return eventPosted;
425 }
426 
postScanRequestAsyncResultEventFatal(uint32_t nanoappInstanceId,bool success,uint8_t errorCode,const void * cookie)427 void WifiRequestManager::postScanRequestAsyncResultEventFatal(
428     uint32_t nanoappInstanceId, bool success, uint8_t errorCode,
429     const void *cookie) {
430   if (!postScanRequestAsyncResultEvent(nanoappInstanceId, success, errorCode,
431                                        cookie)) {
432     FATAL_ERROR("Failed to send WiFi scan request async result event");
433   }
434 }
435 
postScanEventFatal(chreWifiScanEvent * event)436 void WifiRequestManager::postScanEventFatal(chreWifiScanEvent *event) {
437   EventLoopManagerSingleton::get()->getEventLoop()
438       .postEvent(CHRE_EVENT_WIFI_SCAN_RESULT, event, freeWifiScanEventCallback);
439 }
440 
handleScanMonitorStateChangeSync(bool enabled,uint8_t errorCode)441 void WifiRequestManager::handleScanMonitorStateChangeSync(bool enabled,
442                                                           uint8_t errorCode) {
443   // Success is defined as having no errors ... in life ༼ つ ◕_◕ ༽つ
444   bool success = (errorCode == CHRE_ERROR_NONE);
445 
446   // TODO(b/62904616): re-enable this assertion
447   //CHRE_ASSERT_LOG(!mScanMonitorStateTransitions.empty(),
448   //                "handleScanMonitorStateChangeSync called with no transitions");
449   if (mPendingScanMonitorRequests.empty()) {
450     LOGE("WiFi PAL error: handleScanMonitorStateChangeSync called with no "
451          "transitions (enabled %d errorCode %" PRIu8 ")", enabled, errorCode);
452   }
453 
454   // Always check the front of the queue.
455   if (!mPendingScanMonitorRequests.empty()) {
456     const auto& stateTransition = mPendingScanMonitorRequests.front();
457     success &= (stateTransition.enable == enabled);
458     postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
459                                          success, stateTransition.enable,
460                                          errorCode, stateTransition.cookie);
461     mPendingScanMonitorRequests.pop();
462   }
463 
464   while (!mPendingScanMonitorRequests.empty()) {
465     const auto& stateTransition = mPendingScanMonitorRequests.front();
466     bool hasScanMonitorRequest = nanoappHasScanMonitorRequest(
467         stateTransition.nanoappInstanceId);
468     if (scanMonitorIsInRequestedState(
469         stateTransition.enable, hasScanMonitorRequest)) {
470       // We are already in the target state so just post an event indicating
471       // success
472       postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
473                                            true /* success */,
474                                            stateTransition.enable,
475                                            CHRE_ERROR_NONE,
476                                            stateTransition.cookie);
477     } else if (scanMonitorStateTransitionIsRequired(
478         stateTransition.enable, hasScanMonitorRequest)) {
479       if (mPlatformWifi.configureScanMonitor(stateTransition.enable)) {
480         break;
481       } else {
482         postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
483                                              false /* success */,
484                                              stateTransition.enable, CHRE_ERROR,
485                                              stateTransition.cookie);
486       }
487     } else {
488       CHRE_ASSERT_LOG(false, "Invalid scan monitor state");
489       break;
490     }
491 
492     mPendingScanMonitorRequests.pop();
493   }
494 }
495 
handleScanResponseSync(bool pending,uint8_t errorCode)496 void WifiRequestManager::handleScanResponseSync(bool pending,
497                                                 uint8_t errorCode) {
498   // TODO(b/65206783): re-enable this assertion
499   //CHRE_ASSERT_LOG(mScanRequestingNanoappInstanceId.has_value(),
500   //                "handleScanResponseSync called with no outstanding request");
501   if (!mScanRequestingNanoappInstanceId.has_value()) {
502     LOGE("handleScanResponseSync called with no outstanding request");
503   }
504 
505   // TODO: raise this to CHRE_ASSERT_LOG
506   if (!pending && errorCode == CHRE_ERROR_NONE) {
507     LOGE("Invalid wifi scan response");
508     errorCode = CHRE_ERROR;
509   }
510 
511   if (mScanRequestingNanoappInstanceId.has_value()) {
512     bool success = (pending && errorCode == CHRE_ERROR_NONE);
513     if (!success) {
514       LOGW("Wifi scan request failed: pending %d, errorCode %" PRIu8,
515            pending, errorCode);
516     }
517     postScanRequestAsyncResultEventFatal(*mScanRequestingNanoappInstanceId,
518                                          success, errorCode,
519                                          mScanRequestingNanoappCookie);
520 
521     // Set a flag to indicate that results may be pending.
522     mScanRequestResultsArePending = pending;
523 
524     if (pending) {
525       Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
526           .findNanoappByInstanceId(*mScanRequestingNanoappInstanceId);
527       if (nanoapp == nullptr) {
528         LOGW("Received WiFi scan response for unknown nanoapp");
529       } else {
530         nanoapp->registerForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
531       }
532     } else {
533       // If the scan results are not pending, clear the nanoapp instance ID.
534       // Otherwise, wait for the results to be delivered and then clear the
535       // instance ID.
536       mScanRequestingNanoappInstanceId.reset();
537     }
538   }
539 }
540 
postRangingAsyncResult(uint8_t errorCode)541 bool WifiRequestManager::postRangingAsyncResult(uint8_t errorCode) {
542   bool eventPosted = false;
543 
544   if (mPendingRangingRequests.empty()) {
545     LOGE("Unexpected ranging event callback");
546   } else {
547     auto *event = memoryAlloc<struct chreAsyncResult>();
548     if (event == nullptr) {
549       LOG_OOM();
550     } else {
551       const PendingRangingRequest& req = mPendingRangingRequests.front();
552 
553       event->requestType = CHRE_WIFI_REQUEST_TYPE_RANGING;
554       event->success = (errorCode == CHRE_ERROR_NONE);
555       event->errorCode = errorCode;
556       event->reserved = 0;
557       event->cookie = req.cookie;
558 
559       eventPosted = EventLoopManagerSingleton::get()->getEventLoop().postEvent(
560           CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
561           kSystemInstanceId, req.nanoappInstanceId);
562       if (!eventPosted) {
563         memoryFree(event);
564       }
565     }
566   }
567 
568   return eventPosted;
569 }
570 
dispatchQueuedRangingRequest()571 bool WifiRequestManager::dispatchQueuedRangingRequest() {
572   const PendingRangingRequest& req = mPendingRangingRequests.front();
573   struct chreWifiRangingParams params = {};
574   params.targetListLen = static_cast<uint8_t>(req.targetList.size());
575   params.targetList = req.targetList.data();
576 
577   bool success = mPlatformWifi.requestRanging(&params);
578   if (!success) {
579     LOGE("Failed to issue queued ranging result");
580     postRangingAsyncResult(CHRE_ERROR);
581     mPendingRangingRequests.pop();
582   } else {
583     mRangingResponseTimeout = SystemTime::getMonotonicTime()
584         + Nanoseconds(CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS);
585   }
586 
587   return success;
588 }
589 
handleRangingEventSync(uint8_t errorCode,struct chreWifiRangingEvent * event)590 void WifiRequestManager::handleRangingEventSync(
591     uint8_t errorCode, struct chreWifiRangingEvent *event) {
592   if (postRangingAsyncResult(errorCode)) {
593     if (errorCode != CHRE_ERROR_NONE) {
594       LOGW("RTT ranging failed with error %d", errorCode);
595     } else {
596       EventLoopManagerSingleton::get()->getEventLoop().postEvent(
597           CHRE_EVENT_WIFI_RANGING_RESULT, event, freeWifiRangingEventCallback,
598           kSystemInstanceId, mPendingRangingRequests.front().nanoappInstanceId);
599     }
600     mPendingRangingRequests.pop();
601   }
602 
603   // If we have any pending requests, try issuing them to the platform until the
604   // first one succeeds
605   while (!mPendingRangingRequests.empty() && !dispatchQueuedRangingRequest());
606 }
607 
handleFreeWifiScanEvent(chreWifiScanEvent * scanEvent)608 void WifiRequestManager::handleFreeWifiScanEvent(chreWifiScanEvent *scanEvent) {
609   if (mScanRequestResultsArePending) {
610     // Reset the event distribution logic once an entire scan event has been
611     // received and processed by the nanoapp requesting the scan event.
612     mScanEventResultCountAccumulator += scanEvent->resultCount;
613     if (mScanEventResultCountAccumulator >= scanEvent->resultTotal) {
614       mScanEventResultCountAccumulator = 0;
615       mScanRequestResultsArePending = false;
616     }
617 
618     if (!mScanRequestResultsArePending
619         && mScanRequestingNanoappInstanceId.has_value()) {
620       Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
621           .findNanoappByInstanceId(*mScanRequestingNanoappInstanceId);
622       if (nanoapp == nullptr) {
623         LOGW("Attempted to unsubscribe unknown nanoapp from WiFi scan events");
624       } else if (!nanoappHasScanMonitorRequest(
625           *mScanRequestingNanoappInstanceId)) {
626         nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
627       }
628 
629       mScanRequestingNanoappInstanceId.reset();
630     }
631   }
632 
633   mPlatformWifi.releaseScanEvent(scanEvent);
634 }
635 
freeWifiScanEventCallback(uint16_t eventType,void * eventData)636 void WifiRequestManager::freeWifiScanEventCallback(uint16_t eventType,
637                                                    void *eventData) {
638   chreWifiScanEvent *scanEvent = static_cast<chreWifiScanEvent *>(eventData);
639   EventLoopManagerSingleton::get()->getWifiRequestManager()
640       .handleFreeWifiScanEvent(scanEvent);
641 }
642 
freeWifiRangingEventCallback(uint16_t eventType,void * eventData)643 void WifiRequestManager::freeWifiRangingEventCallback(uint16_t eventType,
644                                                       void *eventData) {
645   auto *event = static_cast<struct chreWifiRangingEvent *>(eventData);
646   EventLoopManagerSingleton::get()->getWifiRequestManager()
647       .mPlatformWifi.releaseRangingEvent(event);
648 }
649 
650 }  // namespace chre
651