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 = 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(¶ms);
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