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 LOGE("Couldn't make copy of target list");
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 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
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 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
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 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
scanMonitorIsEnabled() const291 bool WifiRequestManager::scanMonitorIsEnabled() const {
292 return !mScanMonitorNanoapps.empty();
293 }
294
nanoappHasScanMonitorRequest(uint32_t instanceId,size_t * nanoappIndex) const295 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
scanMonitorIsInRequestedState(bool requestedState,bool nanoappHasRequest) const306 bool WifiRequestManager::scanMonitorIsInRequestedState(
307 bool requestedState, bool nanoappHasRequest) const {
308 return (requestedState == scanMonitorIsEnabled() || (!requestedState
309 && (!nanoappHasRequest || mScanMonitorNanoapps.size() > 1)));
310 }
311
scanMonitorStateTransitionIsRequired(bool requestedState,bool nanoappHasRequest) const312 bool WifiRequestManager::scanMonitorStateTransitionIsRequired(
313 bool requestedState, bool nanoappHasRequest) const {
314 return ((requestedState && mScanMonitorNanoapps.empty())
315 || (!requestedState && nanoappHasRequest
316 && mScanMonitorNanoapps.size() == 1));
317 }
318
addScanMonitorRequestToQueue(Nanoapp * nanoapp,bool enable,const void * cookie)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
updateNanoappScanMonitoringList(bool enable,uint32_t instanceId)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
postScanMonitorAsyncResultEvent(uint32_t nanoappInstanceId,bool success,bool enable,uint8_t errorCode,const void * cookie)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
postScanMonitorAsyncResultEventFatal(uint32_t nanoappInstanceId,bool success,bool enable,uint8_t errorCode,const void * cookie)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
postScanRequestAsyncResultEvent(uint32_t nanoappInstanceId,bool success,uint8_t errorCode,const void * cookie)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
postScanRequestAsyncResultEventFatal(uint32_t nanoappInstanceId,bool success,uint8_t errorCode,const void * cookie)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
postScanEventFatal(chreWifiScanEvent * event)445 void WifiRequestManager::postScanEventFatal(chreWifiScanEvent *event) {
446 EventLoopManagerSingleton::get()->getEventLoop()
447 .postEvent(CHRE_EVENT_WIFI_SCAN_RESULT, event, freeWifiScanEventCallback);
448 }
449
handleScanMonitorStateChangeSync(bool enabled,uint8_t errorCode)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
handleScanResponseSync(bool pending,uint8_t errorCode)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
postRangingAsyncResult(uint8_t errorCode)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
dispatchQueuedRangingRequest()578 bool WifiRequestManager::dispatchQueuedRangingRequest() {
579 const PendingRangingRequest& req = mPendingRangingRequests.front();
580 struct chreWifiRangingParams params = {};
581 params.targetListLen = static_cast<uint8_t>(req.targetList.size());
582 params.targetList = req.targetList.data();
583
584 bool success = mPlatformWifi.requestRanging(¶ms);
585 if (!success) {
586 LOGE("Failed to issue queued ranging result");
587 postRangingAsyncResult(CHRE_ERROR);
588 mPendingRangingRequests.pop();
589 } else {
590 mRangingResponseTimeout = SystemTime::getMonotonicTime()
591 + Nanoseconds(CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS);
592 }
593
594 return success;
595 }
596
handleRangingEventSync(uint8_t errorCode,struct chreWifiRangingEvent * event)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
handleFreeWifiScanEvent(chreWifiScanEvent * scanEvent)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
freeWifiScanEventCallback(uint16_t eventType,void * eventData)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
freeWifiRangingEventCallback(uint16_t eventType,void * eventData)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