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(¶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
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 =
384 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
385 CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
386 nanoappInstanceId);
387 if (!eventPosted) {
388 memoryFree(event);
389 }
390 }
391 }
392
393 return eventPosted;
394 }
395
postScanMonitorAsyncResultEventFatal(uint32_t nanoappInstanceId,bool success,bool enable,uint8_t errorCode,const void * cookie)396 void WifiRequestManager::postScanMonitorAsyncResultEventFatal(
397 uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
398 const void *cookie) {
399 if (!postScanMonitorAsyncResultEvent(nanoappInstanceId, success, enable,
400 errorCode, cookie)) {
401 FATAL_ERROR("Failed to send WiFi scan monitor async result event");
402 }
403 }
404
postScanRequestAsyncResultEvent(uint32_t nanoappInstanceId,bool success,uint8_t errorCode,const void * cookie)405 bool WifiRequestManager::postScanRequestAsyncResultEvent(
406 uint32_t nanoappInstanceId, bool success, uint8_t errorCode,
407 const void *cookie) {
408 bool eventPosted = false;
409 chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
410 if (event == nullptr) {
411 LOG_OOM();
412 } else {
413 event->requestType = CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN;
414 event->success = success;
415 event->errorCode = errorCode;
416 event->reserved = 0;
417 event->cookie = cookie;
418
419 // Post the event.
420 eventPosted =
421 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
422 CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
423 nanoappInstanceId);
424 }
425
426 return eventPosted;
427 }
428
postScanRequestAsyncResultEventFatal(uint32_t nanoappInstanceId,bool success,uint8_t errorCode,const void * cookie)429 void WifiRequestManager::postScanRequestAsyncResultEventFatal(
430 uint32_t nanoappInstanceId, bool success, uint8_t errorCode,
431 const void *cookie) {
432 if (!postScanRequestAsyncResultEvent(nanoappInstanceId, success, errorCode,
433 cookie)) {
434 FATAL_ERROR("Failed to send WiFi scan request async result event");
435 }
436 }
437
postScanEventFatal(chreWifiScanEvent * event)438 void WifiRequestManager::postScanEventFatal(chreWifiScanEvent *event) {
439 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
440 CHRE_EVENT_WIFI_SCAN_RESULT, event, freeWifiScanEventCallback);
441 }
442
handleScanMonitorStateChangeSync(bool enabled,uint8_t errorCode)443 void WifiRequestManager::handleScanMonitorStateChangeSync(bool enabled,
444 uint8_t errorCode) {
445 // Success is defined as having no errors ... in life ༼ つ ◕_◕ ༽つ
446 bool success = (errorCode == CHRE_ERROR_NONE);
447
448 // TODO(b/62904616): re-enable this assertion
449 //CHRE_ASSERT_LOG(!mScanMonitorStateTransitions.empty(),
450 // "handleScanMonitorStateChangeSync called with no transitions");
451 if (mPendingScanMonitorRequests.empty()) {
452 LOGE("WiFi PAL error: handleScanMonitorStateChangeSync called with no "
453 "transitions (enabled %d errorCode %" PRIu8 ")", enabled, errorCode);
454 }
455
456 // Always check the front of the queue.
457 if (!mPendingScanMonitorRequests.empty()) {
458 const auto& stateTransition = mPendingScanMonitorRequests.front();
459 success &= (stateTransition.enable == enabled);
460 postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
461 success, stateTransition.enable,
462 errorCode, stateTransition.cookie);
463 mPendingScanMonitorRequests.pop();
464 }
465
466 while (!mPendingScanMonitorRequests.empty()) {
467 const auto& stateTransition = mPendingScanMonitorRequests.front();
468 bool hasScanMonitorRequest = nanoappHasScanMonitorRequest(
469 stateTransition.nanoappInstanceId);
470 if (scanMonitorIsInRequestedState(
471 stateTransition.enable, hasScanMonitorRequest)) {
472 // We are already in the target state so just post an event indicating
473 // success
474 postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
475 true /* success */,
476 stateTransition.enable,
477 CHRE_ERROR_NONE,
478 stateTransition.cookie);
479 } else if (scanMonitorStateTransitionIsRequired(
480 stateTransition.enable, hasScanMonitorRequest)) {
481 if (mPlatformWifi.configureScanMonitor(stateTransition.enable)) {
482 break;
483 } else {
484 postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
485 false /* success */,
486 stateTransition.enable, CHRE_ERROR,
487 stateTransition.cookie);
488 }
489 } else {
490 CHRE_ASSERT_LOG(false, "Invalid scan monitor state");
491 break;
492 }
493
494 mPendingScanMonitorRequests.pop();
495 }
496 }
497
handleScanResponseSync(bool pending,uint8_t errorCode)498 void WifiRequestManager::handleScanResponseSync(bool pending,
499 uint8_t errorCode) {
500 // TODO(b/65206783): re-enable this assertion
501 //CHRE_ASSERT_LOG(mScanRequestingNanoappInstanceId.has_value(),
502 // "handleScanResponseSync called with no outstanding request");
503 if (!mScanRequestingNanoappInstanceId.has_value()) {
504 LOGE("handleScanResponseSync called with no outstanding request");
505 }
506
507 // TODO: raise this to CHRE_ASSERT_LOG
508 if (!pending && errorCode == CHRE_ERROR_NONE) {
509 LOGE("Invalid wifi scan response");
510 errorCode = CHRE_ERROR;
511 }
512
513 if (mScanRequestingNanoappInstanceId.has_value()) {
514 bool success = (pending && errorCode == CHRE_ERROR_NONE);
515 if (!success) {
516 LOGW("Wifi scan request failed: pending %d, errorCode %" PRIu8,
517 pending, errorCode);
518 }
519 postScanRequestAsyncResultEventFatal(*mScanRequestingNanoappInstanceId,
520 success, errorCode,
521 mScanRequestingNanoappCookie);
522
523 // Set a flag to indicate that results may be pending.
524 mScanRequestResultsArePending = pending;
525
526 if (pending) {
527 Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
528 .findNanoappByInstanceId(*mScanRequestingNanoappInstanceId);
529 if (nanoapp == nullptr) {
530 LOGW("Received WiFi scan response for unknown nanoapp");
531 } else {
532 nanoapp->registerForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
533 }
534 } else {
535 // If the scan results are not pending, clear the nanoapp instance ID.
536 // Otherwise, wait for the results to be delivered and then clear the
537 // instance ID.
538 mScanRequestingNanoappInstanceId.reset();
539 }
540 }
541 }
542
postRangingAsyncResult(uint8_t errorCode)543 bool WifiRequestManager::postRangingAsyncResult(uint8_t errorCode) {
544 bool eventPosted = false;
545
546 if (mPendingRangingRequests.empty()) {
547 LOGE("Unexpected ranging event callback");
548 } else {
549 auto *event = memoryAlloc<struct chreAsyncResult>();
550 if (event == nullptr) {
551 LOG_OOM();
552 } else {
553 const PendingRangingRequest& req = mPendingRangingRequests.front();
554
555 event->requestType = CHRE_WIFI_REQUEST_TYPE_RANGING;
556 event->success = (errorCode == CHRE_ERROR_NONE);
557 event->errorCode = errorCode;
558 event->reserved = 0;
559 event->cookie = req.cookie;
560
561 eventPosted =
562 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
563 CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
564 req.nanoappInstanceId);
565 if (!eventPosted) {
566 memoryFree(event);
567 }
568 }
569 }
570
571 return eventPosted;
572 }
573
dispatchQueuedRangingRequest()574 bool WifiRequestManager::dispatchQueuedRangingRequest() {
575 const PendingRangingRequest& req = mPendingRangingRequests.front();
576 struct chreWifiRangingParams params = {};
577 params.targetListLen = static_cast<uint8_t>(req.targetList.size());
578 params.targetList = req.targetList.data();
579
580 bool success = mPlatformWifi.requestRanging(¶ms);
581 if (!success) {
582 LOGE("Failed to issue queued ranging result");
583 postRangingAsyncResult(CHRE_ERROR);
584 mPendingRangingRequests.pop();
585 } else {
586 mRangingResponseTimeout = SystemTime::getMonotonicTime()
587 + Nanoseconds(CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS);
588 }
589
590 return success;
591 }
592
handleRangingEventSync(uint8_t errorCode,struct chreWifiRangingEvent * event)593 void WifiRequestManager::handleRangingEventSync(
594 uint8_t errorCode, struct chreWifiRangingEvent *event) {
595 if (postRangingAsyncResult(errorCode)) {
596 if (errorCode != CHRE_ERROR_NONE) {
597 LOGW("RTT ranging failed with error %d", errorCode);
598 } else {
599 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
600 CHRE_EVENT_WIFI_RANGING_RESULT, event, freeWifiRangingEventCallback,
601 mPendingRangingRequests.front().nanoappInstanceId);
602 }
603 mPendingRangingRequests.pop();
604 }
605
606 // If we have any pending requests, try issuing them to the platform until the
607 // first one succeeds
608 while (!mPendingRangingRequests.empty() && !dispatchQueuedRangingRequest());
609 }
610
handleFreeWifiScanEvent(chreWifiScanEvent * scanEvent)611 void WifiRequestManager::handleFreeWifiScanEvent(chreWifiScanEvent *scanEvent) {
612 if (mScanRequestResultsArePending) {
613 // Reset the event distribution logic once an entire scan event has been
614 // received and processed by the nanoapp requesting the scan event.
615 mScanEventResultCountAccumulator += scanEvent->resultCount;
616 if (mScanEventResultCountAccumulator >= scanEvent->resultTotal) {
617 mScanEventResultCountAccumulator = 0;
618 mScanRequestResultsArePending = false;
619 }
620
621 if (!mScanRequestResultsArePending
622 && mScanRequestingNanoappInstanceId.has_value()) {
623 Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
624 .findNanoappByInstanceId(*mScanRequestingNanoappInstanceId);
625 if (nanoapp == nullptr) {
626 LOGW("Attempted to unsubscribe unknown nanoapp from WiFi scan events");
627 } else if (!nanoappHasScanMonitorRequest(
628 *mScanRequestingNanoappInstanceId)) {
629 nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
630 }
631
632 mScanRequestingNanoappInstanceId.reset();
633 }
634 }
635
636 mPlatformWifi.releaseScanEvent(scanEvent);
637 }
638
freeWifiScanEventCallback(uint16_t eventType,void * eventData)639 void WifiRequestManager::freeWifiScanEventCallback(uint16_t eventType,
640 void *eventData) {
641 chreWifiScanEvent *scanEvent = static_cast<chreWifiScanEvent *>(eventData);
642 EventLoopManagerSingleton::get()->getWifiRequestManager()
643 .handleFreeWifiScanEvent(scanEvent);
644 }
645
freeWifiRangingEventCallback(uint16_t eventType,void * eventData)646 void WifiRequestManager::freeWifiRangingEventCallback(uint16_t eventType,
647 void *eventData) {
648 auto *event = static_cast<struct chreWifiRangingEvent *>(eventData);
649 EventLoopManagerSingleton::get()->getWifiRequestManager()
650 .mPlatformWifi.releaseRangingEvent(event);
651 }
652
653 } // namespace chre
654