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 "chre/core/wifi_request_manager.h"
18
19 #include <cinttypes>
20 #include <cstddef>
21 #include <cstdint>
22 #include <cstring>
23
24 #include "chre/core/event_loop_manager.h"
25 #include "chre/core/settings.h"
26 #include "chre/core/system_health_monitor.h"
27 #include "chre/platform/fatal_error.h"
28 #include "chre/platform/log.h"
29 #include "chre/platform/system_time.h"
30 #include "chre/util/nested_data_ptr.h"
31 #include "chre/util/system/debug_dump.h"
32 #include "chre/util/system/event_callbacks.h"
33 #include "chre_api/chre/version.h"
34 #include "include/chre/core/event_loop_common.h"
35 #include "include/chre/core/wifi_request_manager.h"
36
37 // The default timeout values can be overwritten to lower the runtime
38 // for tests. Timeout values cannot be overwritten with a bigger value.
39 #ifdef CHRE_TEST_ASYNC_RESULT_TIMEOUT_NS
40 static_assert(CHRE_TEST_ASYNC_RESULT_TIMEOUT_NS <=
41 CHRE_ASYNC_RESULT_TIMEOUT_NS);
42 #undef CHRE_ASYNC_RESULT_TIMEOUT_NS
43 #define CHRE_ASYNC_RESULT_TIMEOUT_NS CHRE_TEST_ASYNC_RESULT_TIMEOUT_NS
44 #endif
45
46 #ifdef CHRE_TEST_WIFI_RANGING_RESULT_TIMEOUT_NS
47 static_assert(CHRE_TEST_WIFI_RANGING_RESULT_TIMEOUT_NS <=
48 CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS);
49 #undef CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS
50 #define CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS \
51 CHRE_TEST_WIFI_RANGING_RESULT_TIMEOUT_NS
52 #endif
53
54 #ifdef CHRE_TEST_WIFI_SCAN_RESULT_TIMEOUT_NS
55 static_assert(CHRE_TEST_WIFI_SCAN_RESULT_TIMEOUT_NS <=
56 CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS);
57 #undef CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS
58 #define CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS CHRE_TEST_WIFI_SCAN_RESULT_TIMEOUT_NS
59 #endif
60
61 namespace chre {
62
WifiRequestManager()63 WifiRequestManager::WifiRequestManager() {
64 // Reserve space for at least one scan monitoring nanoapp. This ensures that
65 // the first asynchronous push_back will succeed. Future push_backs will be
66 // synchronous and failures will be returned to the client.
67 if (!mScanMonitorNanoapps.reserve(1)) {
68 FATAL_ERROR_OOM();
69 }
70 }
71
init()72 void WifiRequestManager::init() {
73 mPlatformWifi.init();
74 }
75
getCapabilities()76 uint32_t WifiRequestManager::getCapabilities() {
77 return mPlatformWifi.getCapabilities();
78 }
79
dispatchQueuedConfigureScanMonitorRequests()80 void WifiRequestManager::dispatchQueuedConfigureScanMonitorRequests() {
81 while (!mPendingScanMonitorRequests.empty()) {
82 const auto &stateTransition = mPendingScanMonitorRequests.front();
83 bool hasScanMonitorRequest =
84 nanoappHasScanMonitorRequest(stateTransition.nanoappInstanceId);
85 if (scanMonitorIsInRequestedState(stateTransition.enable,
86 hasScanMonitorRequest)) {
87 // We are already in the target state so just post an event indicating
88 // success
89 postScanMonitorAsyncResultEventFatal(
90 stateTransition.nanoappInstanceId, true /* success */,
91 stateTransition.enable, CHRE_ERROR_NONE, stateTransition.cookie);
92 } else if (scanMonitorStateTransitionIsRequired(stateTransition.enable,
93 hasScanMonitorRequest)) {
94 if (!mPlatformWifi.configureScanMonitor(stateTransition.enable)) {
95 postScanMonitorAsyncResultEventFatal(
96 stateTransition.nanoappInstanceId, false /* success */,
97 stateTransition.enable, CHRE_ERROR, stateTransition.cookie);
98 } else {
99 mConfigureScanMonitorTimeoutHandle = setConfigureScanMonitorTimer();
100 break;
101 }
102 } else {
103 CHRE_ASSERT_LOG(false, "Invalid scan monitor state");
104 }
105 mPendingScanMonitorRequests.pop();
106 }
107 }
108
handleConfigureScanMonitorTimeout()109 void WifiRequestManager::handleConfigureScanMonitorTimeout() {
110 if (mPendingScanMonitorRequests.empty()) {
111 LOGE("Configure Scan Monitor timer timedout with no pending request.");
112 } else {
113 EventLoopManagerSingleton::get()->getSystemHealthMonitor().onFailure(
114 HealthCheckId::WifiConfigureScanMonitorTimeout);
115 mPendingScanMonitorRequests.pop();
116
117 dispatchQueuedConfigureScanMonitorRequests();
118 }
119 }
120
setConfigureScanMonitorTimer()121 TimerHandle WifiRequestManager::setConfigureScanMonitorTimer() {
122 auto callback = [](uint16_t /*type*/, void * /*data*/, void * /*extraData*/) {
123 EventLoopManagerSingleton::get()
124 ->getWifiRequestManager()
125 .handleConfigureScanMonitorTimeout();
126 };
127
128 return EventLoopManagerSingleton::get()->setDelayedCallback(
129 SystemCallbackType::RequestTimeoutEvent, nullptr, callback,
130 Nanoseconds(CHRE_ASYNC_RESULT_TIMEOUT_NS));
131 }
132
configureScanMonitor(Nanoapp * nanoapp,bool enable,const void * cookie)133 bool WifiRequestManager::configureScanMonitor(Nanoapp *nanoapp, bool enable,
134 const void *cookie) {
135 CHRE_ASSERT(nanoapp);
136
137 bool success = false;
138 uint16_t instanceId = nanoapp->getInstanceId();
139 bool hasScanMonitorRequest = nanoappHasScanMonitorRequest(instanceId);
140 if (!mPendingScanMonitorRequests.empty()) {
141 success = addScanMonitorRequestToQueue(nanoapp, enable, cookie);
142 } else if (scanMonitorIsInRequestedState(enable, hasScanMonitorRequest)) {
143 // The scan monitor is already in the requested state. A success event can
144 // be posted immediately.
145 success = postScanMonitorAsyncResultEvent(instanceId, true /* success */,
146 enable, CHRE_ERROR_NONE, cookie);
147 } else if (scanMonitorStateTransitionIsRequired(enable,
148 hasScanMonitorRequest)) {
149 success = addScanMonitorRequestToQueue(nanoapp, enable, cookie);
150 if (success) {
151 success = mPlatformWifi.configureScanMonitor(enable);
152 if (!success) {
153 mPendingScanMonitorRequests.pop_back();
154 LOGE("Failed to enable the scan monitor for nanoapp instance %" PRIu16,
155 instanceId);
156 } else {
157 mConfigureScanMonitorTimeoutHandle = setConfigureScanMonitorTimer();
158 }
159 }
160 } else {
161 CHRE_ASSERT_LOG(false, "Invalid scan monitor configuration");
162 }
163
164 return success;
165 }
166
disableAllSubscriptions(Nanoapp * nanoapp)167 uint32_t WifiRequestManager::disableAllSubscriptions(Nanoapp *nanoapp) {
168 uint32_t numSubscriptionsDisabled = 0;
169
170 // Disable active scan monitoring.
171 if (nanoappHasScanMonitorRequest(nanoapp->getInstanceId()) ||
172 nanoappHasPendingScanMonitorRequest(nanoapp->getInstanceId())) {
173 numSubscriptionsDisabled++;
174 configureScanMonitor(nanoapp, false /*enabled*/, nullptr /*cookie*/);
175 }
176
177 // Disable active NAN subscriptions.
178 for (size_t i = 0; i < mNanoappSubscriptions.size(); ++i) {
179 if (mNanoappSubscriptions[i].nanoappInstanceId ==
180 nanoapp->getInstanceId()) {
181 numSubscriptionsDisabled++;
182 nanSubscribeCancel(nanoapp, mNanoappSubscriptions[i].subscriptionId);
183 }
184 }
185
186 return numSubscriptionsDisabled;
187 }
188
requestRangingByType(RangingType type,const void * rangingParams)189 bool WifiRequestManager::requestRangingByType(RangingType type,
190 const void *rangingParams) {
191 bool success = false;
192 if (type == RangingType::WIFI_AP) {
193 auto *params =
194 static_cast<const struct chreWifiRangingParams *>(rangingParams);
195 success = mPlatformWifi.requestRanging(params);
196 } else {
197 auto *params =
198 static_cast<const struct chreWifiNanRangingParams *>(rangingParams);
199 success = mPlatformWifi.requestNanRanging(params);
200 }
201 if (success) {
202 mRequestRangingTimeoutHandle = setRangingRequestTimer();
203 }
204 return success;
205 }
206
updateRangingRequest(RangingType type,PendingRangingRequest & request,const void * rangingParams)207 bool WifiRequestManager::updateRangingRequest(RangingType type,
208 PendingRangingRequest &request,
209 const void *rangingParams) {
210 bool success = false;
211 if (type == RangingType::WIFI_AP) {
212 auto *params =
213 static_cast<const struct chreWifiRangingParams *>(rangingParams);
214 success = request.targetList.copy_array(params->targetList,
215 params->targetListLen);
216 } else {
217 auto *params =
218 static_cast<const struct chreWifiNanRangingParams *>(rangingParams);
219 std::memcpy(request.nanRangingParams.macAddress, params->macAddress,
220 CHRE_WIFI_BSSID_LEN);
221 success = true;
222 }
223 return success;
224 }
225
sendRangingRequest(PendingRangingRequest & request)226 bool WifiRequestManager::sendRangingRequest(PendingRangingRequest &request) {
227 bool success = false;
228
229 if (request.type == RangingType::WIFI_AP) {
230 struct chreWifiRangingParams params = {};
231 params.targetListLen = static_cast<uint8_t>(request.targetList.size());
232 params.targetList = request.targetList.data();
233 success = mPlatformWifi.requestRanging(¶ms);
234 } else {
235 struct chreWifiNanRangingParams params;
236 std::memcpy(params.macAddress, request.nanRangingParams.macAddress,
237 CHRE_WIFI_BSSID_LEN);
238 success = mPlatformWifi.requestNanRanging(¶ms);
239 }
240 if (success) {
241 mRequestRangingTimeoutHandle = setRangingRequestTimer();
242 }
243 return success;
244 }
245
handleRangingRequestTimeout()246 void WifiRequestManager::handleRangingRequestTimeout() {
247 if (mPendingRangingRequests.empty()) {
248 LOGE("Request ranging timer timedout with no pending request.");
249 } else {
250 EventLoopManagerSingleton::get()->getSystemHealthMonitor().onFailure(
251 HealthCheckId::WifiRequestRangingTimeout);
252 mPendingRangingRequests.pop();
253 while (!mPendingRangingRequests.empty() && !dispatchQueuedRangingRequest())
254 ;
255 }
256 }
257
setRangingRequestTimer()258 TimerHandle WifiRequestManager::setRangingRequestTimer() {
259 auto callback = [](uint16_t /*type*/, void * /*data*/, void * /*extraData*/) {
260 EventLoopManagerSingleton::get()
261 ->getWifiRequestManager()
262 .handleRangingRequestTimeout();
263 };
264
265 return EventLoopManagerSingleton::get()->setDelayedCallback(
266 SystemCallbackType::RequestTimeoutEvent, nullptr, callback,
267 Nanoseconds(CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS));
268 }
269
requestRanging(RangingType rangingType,Nanoapp * nanoapp,const void * rangingParams,const void * cookie)270 bool WifiRequestManager::requestRanging(RangingType rangingType,
271 Nanoapp *nanoapp,
272 const void *rangingParams,
273 const void *cookie) {
274 CHRE_ASSERT(nanoapp);
275 CHRE_ASSERT(rangingParams);
276
277 bool success = false;
278 if (!mPendingRangingRequests.emplace()) {
279 LOGE("Can't issue new RTT request; pending queue full");
280 } else {
281 PendingRangingRequest &req = mPendingRangingRequests.back();
282 req.nanoappInstanceId = nanoapp->getInstanceId();
283 req.cookie = cookie;
284 if (mPendingRangingRequests.size() == 1) {
285 // First in line; dispatch request immediately
286 if (!areRequiredSettingsEnabled()) {
287 // Treat as success but post async failure per API.
288 success = true;
289 postRangingAsyncResult(CHRE_ERROR_FUNCTION_DISABLED);
290 mPendingRangingRequests.pop_back();
291 } else if (!requestRangingByType(rangingType, rangingParams)) {
292 LOGE("WiFi ranging request of type %d failed",
293 static_cast<int>(rangingType));
294 mPendingRangingRequests.pop_back();
295 } else {
296 success = true;
297 }
298 } else {
299 success = updateRangingRequest(rangingType, req, rangingParams);
300 if (!success) {
301 LOG_OOM();
302 mPendingRangingRequests.pop_back();
303 }
304 }
305 }
306 return success;
307 }
308
handleScanRequestTimeout()309 void WifiRequestManager::handleScanRequestTimeout() {
310 mScanRequestTimeoutHandle = CHRE_TIMER_INVALID;
311 if (mPendingScanRequests.empty()) {
312 LOGE("Scan Request timer timedout with no pending request.");
313 } else {
314 EventLoopManagerSingleton::get()->getSystemHealthMonitor().onFailure(
315 HealthCheckId::WifiScanResponseTimeout);
316 mPendingScanRequests.pop();
317 dispatchQueuedScanRequests(true /* postAsyncResult */);
318 }
319 }
320
setScanRequestTimer()321 TimerHandle WifiRequestManager::setScanRequestTimer() {
322 CHRE_ASSERT(mScanRequestTimeoutHandle == CHRE_TIMER_INVALID);
323
324 auto callback = [](uint16_t /*type*/, void * /*data*/, void * /*extraData*/) {
325 EventLoopManagerSingleton::get()
326 ->getWifiRequestManager()
327 .handleScanRequestTimeout();
328 };
329
330 return EventLoopManagerSingleton::get()->setDelayedCallback(
331 SystemCallbackType::RequestTimeoutEvent, nullptr, callback,
332 Nanoseconds(CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS));
333 }
334
nanoappHasPendingScanRequest(uint16_t instanceId) const335 bool WifiRequestManager::nanoappHasPendingScanRequest(
336 uint16_t instanceId) const {
337 for (const auto &scanRequest : mPendingScanRequests) {
338 if (scanRequest.nanoappInstanceId == instanceId) {
339 return true;
340 }
341 }
342 return false;
343 }
344
requestScan(Nanoapp * nanoapp,const struct chreWifiScanParams * params,const void * cookie)345 bool WifiRequestManager::requestScan(Nanoapp *nanoapp,
346 const struct chreWifiScanParams *params,
347 const void *cookie) {
348 CHRE_ASSERT(nanoapp);
349
350 // Handle compatibility with nanoapps compiled against API v1.1, which doesn't
351 // include the radioChainPref parameter in chreWifiScanParams
352 struct chreWifiScanParams paramsCompat;
353 if (nanoapp->getTargetApiVersion() < CHRE_API_VERSION_1_2) {
354 memcpy(¶msCompat, params, offsetof(chreWifiScanParams, radioChainPref));
355 paramsCompat.radioChainPref = CHRE_WIFI_RADIO_CHAIN_PREF_DEFAULT;
356 params = ¶msCompat;
357 }
358
359 bool success = false;
360 uint16_t nanoappInstanceId = nanoapp->getInstanceId();
361 if (nanoappHasPendingScanRequest(nanoappInstanceId)) {
362 LOGE("Can't issue new scan request: nanoapp: %" PRIx64
363 " already has a pending request",
364 nanoapp->getAppId());
365 } else if (!mPendingScanRequests.emplace(nanoappInstanceId, cookie, params)) {
366 LOG_OOM();
367 } else if (!EventLoopManagerSingleton::get()
368 ->getSettingManager()
369 .getSettingEnabled(Setting::WIFI_AVAILABLE)) {
370 // Treat as success, but send an async failure per API contract.
371 success = true;
372 handleScanResponse(false /* pending */, CHRE_ERROR_FUNCTION_DISABLED);
373 } else {
374 if (mPendingScanRequests.size() == 1) {
375 success = dispatchQueuedScanRequests(false /* postAsyncResult */);
376 } else {
377 success = true;
378 }
379 }
380
381 return success;
382 }
383
handleScanMonitorStateChange(bool enabled,uint8_t errorCode)384 void WifiRequestManager::handleScanMonitorStateChange(bool enabled,
385 uint8_t errorCode) {
386 EventLoopManagerSingleton::get()->cancelDelayedCallback(
387 mConfigureScanMonitorTimeoutHandle);
388 struct CallbackState {
389 bool enabled;
390 uint8_t errorCode;
391 };
392
393 auto callback = [](uint16_t /*type*/, void *data, void * /*extraData*/) {
394 CallbackState cbState = NestedDataPtr<CallbackState>(data);
395 EventLoopManagerSingleton::get()
396 ->getWifiRequestManager()
397 .handleScanMonitorStateChangeSync(cbState.enabled, cbState.errorCode);
398 };
399
400 CallbackState cbState = {};
401 cbState.enabled = enabled;
402 cbState.errorCode = errorCode;
403 EventLoopManagerSingleton::get()->deferCallback(
404 SystemCallbackType::WifiScanMonitorStateChange,
405 NestedDataPtr<CallbackState>(cbState), callback);
406 }
407
handleScanResponse(bool pending,uint8_t errorCode)408 void WifiRequestManager::handleScanResponse(bool pending, uint8_t errorCode) {
409 struct CallbackState {
410 bool pending;
411 uint8_t errorCode;
412 };
413
414 auto callback = [](uint16_t /*type*/, void *data, void * /*extraData*/) {
415 CallbackState cbState = NestedDataPtr<CallbackState>(data);
416 EventLoopManagerSingleton::get()
417 ->getWifiRequestManager()
418 .handleScanResponseSync(cbState.pending, cbState.errorCode);
419 };
420
421 CallbackState cbState = {};
422 cbState.pending = pending;
423 cbState.errorCode = errorCode;
424 EventLoopManagerSingleton::get()->deferCallback(
425 SystemCallbackType::WifiRequestScanResponse,
426 NestedDataPtr<CallbackState>(cbState), callback);
427 }
428
handleRangingEvent(uint8_t errorCode,struct chreWifiRangingEvent * event)429 void WifiRequestManager::handleRangingEvent(
430 uint8_t errorCode, struct chreWifiRangingEvent *event) {
431 EventLoopManagerSingleton::get()->cancelDelayedCallback(
432 mRequestRangingTimeoutHandle);
433 auto callback = [](uint16_t /*type*/, void *data, void *extraData) {
434 uint8_t cbErrorCode = NestedDataPtr<uint8_t>(extraData);
435 EventLoopManagerSingleton::get()
436 ->getWifiRequestManager()
437 .handleRangingEventSync(
438 cbErrorCode, static_cast<struct chreWifiRangingEvent *>(data));
439 };
440
441 EventLoopManagerSingleton::get()->deferCallback(
442 SystemCallbackType::WifiHandleRangingEvent, event, callback,
443 NestedDataPtr<uint8_t>(errorCode));
444 }
445
handleScanEvent(struct chreWifiScanEvent * event)446 void WifiRequestManager::handleScanEvent(struct chreWifiScanEvent *event) {
447 auto callback = [](uint16_t /*type*/, void *data, void * /*extraData*/) {
448 auto *scanEvent = static_cast<struct chreWifiScanEvent *>(data);
449 EventLoopManagerSingleton::get()
450 ->getWifiRequestManager()
451 .postScanEventFatal(scanEvent);
452 };
453
454 EventLoopManagerSingleton::get()->deferCallback(
455 SystemCallbackType::WifiHandleScanEvent, event, callback);
456 }
457
handleNanServiceIdentifierEventSync(uint8_t errorCode,uint32_t subscriptionId)458 void WifiRequestManager::handleNanServiceIdentifierEventSync(
459 uint8_t errorCode, uint32_t subscriptionId) {
460 if (!mPendingNanSubscribeRequests.empty()) {
461 auto &req = mPendingNanSubscribeRequests.front();
462 chreWifiNanIdentifierEvent *event =
463 memoryAlloc<chreWifiNanIdentifierEvent>();
464
465 if (event == nullptr) {
466 LOG_OOM();
467 } else {
468 event->id = subscriptionId;
469 event->result.requestType = CHRE_WIFI_REQUEST_TYPE_NAN_SUBSCRIBE;
470 event->result.success = (errorCode == CHRE_ERROR_NONE);
471 event->result.errorCode = errorCode;
472 event->result.cookie = req.cookie;
473
474 if (errorCode == CHRE_ERROR_NONE) {
475 // It is assumed that the NAN discovery engine guarantees a unique ID
476 // for each subscription - avoid redundant checks on uniqueness here.
477 if (!mNanoappSubscriptions.push_back(NanoappNanSubscriptions(
478 req.nanoappInstanceId, subscriptionId))) {
479 LOG_OOM();
480 // Even though the subscription request was able to successfully
481 // obtain an ID, CHRE ran out of memory and couldn't store the
482 // instance ID - subscription ID pair. Indicate this in the event
483 // result.
484 // TODO(b/204226580): Cancel the subscription if we run out of
485 // memory.
486 event->result.errorCode = CHRE_ERROR_NO_MEMORY;
487 }
488 }
489
490 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
491 CHRE_EVENT_WIFI_NAN_IDENTIFIER_RESULT, event, freeEventDataCallback,
492 req.nanoappInstanceId);
493 }
494
495 mPendingNanSubscribeRequests.pop();
496 dispatchQueuedNanSubscribeRequestWithRetry();
497 } else {
498 LOGE("Received a NAN identifier event with no pending request!");
499 }
500 }
501
handleNanServiceIdentifierEvent(uint8_t errorCode,uint32_t subscriptionId)502 void WifiRequestManager::handleNanServiceIdentifierEvent(
503 uint8_t errorCode, uint32_t subscriptionId) {
504 auto callback = [](uint16_t /*type*/, void *data, void *extraData) {
505 uint8_t errorCode = NestedDataPtr<uint8_t>(data);
506 uint32_t subscriptionId = NestedDataPtr<uint32_t>(extraData);
507 EventLoopManagerSingleton::get()
508 ->getWifiRequestManager()
509 .handleNanServiceIdentifierEventSync(errorCode, subscriptionId);
510 };
511
512 EventLoopManagerSingleton::get()->deferCallback(
513 SystemCallbackType::WifiNanServiceIdEvent,
514 NestedDataPtr<uint8_t>(errorCode), callback,
515 NestedDataPtr<uint32_t>(subscriptionId));
516 }
517
getNappIdFromSubscriptionId(uint32_t subscriptionId,uint16_t * nanoappInstanceId)518 bool WifiRequestManager::getNappIdFromSubscriptionId(
519 uint32_t subscriptionId, uint16_t *nanoappInstanceId) {
520 bool success = false;
521 for (auto &sub : mNanoappSubscriptions) {
522 if (sub.subscriptionId == subscriptionId) {
523 *nanoappInstanceId = sub.nanoappInstanceId;
524 success = true;
525 break;
526 }
527 }
528 return success;
529 }
530
handleNanServiceDiscoveryEventSync(struct chreWifiNanDiscoveryEvent * event)531 void WifiRequestManager::handleNanServiceDiscoveryEventSync(
532 struct chreWifiNanDiscoveryEvent *event) {
533 CHRE_ASSERT(event != nullptr);
534 uint16_t nanoappInstanceId;
535 if (getNappIdFromSubscriptionId(event->subscribeId, &nanoappInstanceId)) {
536 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
537 CHRE_EVENT_WIFI_NAN_DISCOVERY_RESULT, event,
538 freeNanDiscoveryEventCallback, nanoappInstanceId);
539 } else {
540 LOGE("Failed to find a nanoapp owning subscription ID %" PRIu32,
541 event->subscribeId);
542 }
543 }
544
handleNanServiceDiscoveryEvent(struct chreWifiNanDiscoveryEvent * event)545 void WifiRequestManager::handleNanServiceDiscoveryEvent(
546 struct chreWifiNanDiscoveryEvent *event) {
547 auto callback = [](uint16_t /*type*/, void *data, void * /*extraData*/) {
548 auto *event = static_cast<chreWifiNanDiscoveryEvent *>(data);
549 EventLoopManagerSingleton::get()
550 ->getWifiRequestManager()
551 .handleNanServiceDiscoveryEventSync(event);
552 };
553
554 EventLoopManagerSingleton::get()->deferCallback(
555 SystemCallbackType::WifiNanServiceDiscoveryEvent, event, callback);
556 }
557
handleNanServiceLostEventSync(uint32_t subscriptionId,uint32_t publisherId)558 void WifiRequestManager::handleNanServiceLostEventSync(uint32_t subscriptionId,
559 uint32_t publisherId) {
560 uint16_t nanoappInstanceId;
561 if (getNappIdFromSubscriptionId(subscriptionId, &nanoappInstanceId)) {
562 chreWifiNanSessionLostEvent *event =
563 memoryAlloc<chreWifiNanSessionLostEvent>();
564 if (event == nullptr) {
565 LOG_OOM();
566 } else {
567 event->id = subscriptionId;
568 event->peerId = publisherId;
569 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
570 CHRE_EVENT_WIFI_NAN_SESSION_LOST, event, freeEventDataCallback,
571 nanoappInstanceId);
572 }
573 } else {
574 LOGE("Failed to find a nanoapp owning subscription ID %" PRIu32,
575 subscriptionId);
576 }
577 }
578
handleNanServiceLostEvent(uint32_t subscriptionId,uint32_t publisherId)579 void WifiRequestManager::handleNanServiceLostEvent(uint32_t subscriptionId,
580 uint32_t publisherId) {
581 auto callback = [](uint16_t /*type*/, void *data, void *extraData) {
582 auto subscriptionId = NestedDataPtr<uint32_t>(data);
583 auto publisherId = NestedDataPtr<uint32_t>(extraData);
584 EventLoopManagerSingleton::get()
585 ->getWifiRequestManager()
586 .handleNanServiceLostEventSync(subscriptionId, publisherId);
587 };
588
589 EventLoopManagerSingleton::get()->deferCallback(
590 SystemCallbackType::WifiNanServiceSessionLostEvent,
591 NestedDataPtr<uint32_t>(subscriptionId), callback,
592 NestedDataPtr<uint32_t>(publisherId));
593 }
594
handleNanServiceTerminatedEventSync(uint8_t errorCode,uint32_t subscriptionId)595 void WifiRequestManager::handleNanServiceTerminatedEventSync(
596 uint8_t errorCode, uint32_t subscriptionId) {
597 uint16_t nanoappInstanceId;
598 if (getNappIdFromSubscriptionId(subscriptionId, &nanoappInstanceId)) {
599 chreWifiNanSessionTerminatedEvent *event =
600 memoryAlloc<chreWifiNanSessionTerminatedEvent>();
601 if (event == nullptr) {
602 LOG_OOM();
603 } else {
604 event->id = subscriptionId;
605 event->reason = errorCode;
606 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
607 CHRE_EVENT_WIFI_NAN_SESSION_TERMINATED, event, freeEventDataCallback,
608 nanoappInstanceId);
609 }
610 } else {
611 LOGE("Failed to find a nanoapp owning subscription ID %" PRIu32,
612 subscriptionId);
613 }
614 }
615
handleNanServiceSubscriptionCanceledEventSync(uint8_t errorCode,uint32_t subscriptionId)616 void WifiRequestManager::handleNanServiceSubscriptionCanceledEventSync(
617 uint8_t errorCode, uint32_t subscriptionId) {
618 for (size_t i = 0; i < mNanoappSubscriptions.size(); ++i) {
619 if (mNanoappSubscriptions[i].subscriptionId == subscriptionId) {
620 if (errorCode != CHRE_ERROR_NONE) {
621 LOGE("Subscription %" PRIu32 " cancelation error: %" PRIu8,
622 subscriptionId, errorCode);
623 }
624 mNanoappSubscriptions.erase(i);
625 break;
626 }
627 }
628 }
629
handleNanServiceTerminatedEvent(uint8_t errorCode,uint32_t subscriptionId)630 void WifiRequestManager::handleNanServiceTerminatedEvent(
631 uint8_t errorCode, uint32_t subscriptionId) {
632 auto callback = [](uint16_t /*type*/, void *data, void *extraData) {
633 auto errorCode = NestedDataPtr<uint8_t>(data);
634 auto subscriptionId = NestedDataPtr<uint32_t>(extraData);
635 EventLoopManagerSingleton::get()
636 ->getWifiRequestManager()
637 .handleNanServiceTerminatedEventSync(errorCode, subscriptionId);
638 };
639
640 EventLoopManagerSingleton::get()->deferCallback(
641 SystemCallbackType::WifiNanServiceTerminatedEvent,
642 NestedDataPtr<uint8_t>(errorCode), callback,
643 NestedDataPtr<uint32_t>(subscriptionId));
644 }
645
handleNanServiceSubscriptionCanceledEvent(uint8_t errorCode,uint32_t subscriptionId)646 void WifiRequestManager::handleNanServiceSubscriptionCanceledEvent(
647 uint8_t errorCode, uint32_t subscriptionId) {
648 auto callback = [](uint16_t /*type*/, void *data, void *extraData) {
649 auto errorCode = NestedDataPtr<uint8_t>(data);
650 auto subscriptionId = NestedDataPtr<uint32_t>(extraData);
651 EventLoopManagerSingleton::get()
652 ->getWifiRequestManager()
653 .handleNanServiceSubscriptionCanceledEventSync(errorCode,
654 subscriptionId);
655 };
656
657 EventLoopManagerSingleton::get()->deferCallback(
658 SystemCallbackType::WifiNanServiceTerminatedEvent,
659 NestedDataPtr<uint8_t>(errorCode), callback,
660 NestedDataPtr<uint32_t>(subscriptionId));
661 }
662
logStateToBuffer(DebugDumpWrapper & debugDump) const663 void WifiRequestManager::logStateToBuffer(DebugDumpWrapper &debugDump) const {
664 debugDump.print("\nWifi scan monitor %s\n",
665 scanMonitorIsEnabled() ? "enabled" : "disabled");
666
667 if (scanMonitorIsEnabled()) {
668 debugDump.print(" Wifi scan monitor enabled nanoapps:\n");
669 for (uint16_t instanceId : mScanMonitorNanoapps) {
670 debugDump.print(" nappId=%" PRIu16 "\n", instanceId);
671 }
672 }
673
674 if (!mPendingScanRequests.empty()) {
675 debugDump.print(" Wifi scan request queue:\n");
676 for (const auto &request : mPendingScanRequests) {
677 debugDump.print(" nappId=%" PRIu16, request.nanoappInstanceId);
678 }
679 }
680
681 if (!mPendingScanMonitorRequests.empty()) {
682 debugDump.print(" Wifi transition queue:\n");
683 for (const auto &transition : mPendingScanMonitorRequests) {
684 debugDump.print(" enable=%s nappId=%" PRIu16 "\n",
685 transition.enable ? "true" : "false",
686 transition.nanoappInstanceId);
687 }
688 }
689
690 debugDump.print(" Last %zu wifi scan requests:\n",
691 mWifiScanRequestLogs.size());
692 static_assert(kNumWifiRequestLogs <= INT8_MAX,
693 "kNumWifiRequestLogs must be <= INT8_MAX");
694
695 for (int8_t i = static_cast<int8_t>(mWifiScanRequestLogs.size()) - 1; i >= 0;
696 i--) {
697 const auto &log = mWifiScanRequestLogs[static_cast<size_t>(i)];
698 debugDump.print(" ts=%" PRIu64 " nappId=%" PRIu16 " scanType=%" PRIu8
699 " maxScanAge(ms)=%" PRIu64 "\n",
700 log.timestamp.toRawNanoseconds(), log.instanceId,
701 log.scanType, log.maxScanAgeMs.getMilliseconds());
702 }
703
704 debugDump.print(" Last scan event @ %" PRIu64 " ms\n",
705 mLastScanEventTime.getMilliseconds());
706
707 debugDump.print(" API error distribution (error-code indexed):\n");
708 debugDump.print(" Scan monitor:\n");
709 debugDump.logErrorHistogram(mScanMonitorErrorHistogram,
710 ARRAY_SIZE(mScanMonitorErrorHistogram));
711 debugDump.print(" Active Scan:\n");
712 debugDump.logErrorHistogram(mActiveScanErrorHistogram,
713 ARRAY_SIZE(mActiveScanErrorHistogram));
714
715 if (!mNanoappSubscriptions.empty()) {
716 debugDump.print(" Active NAN service subscriptions:\n");
717 for (const auto &sub : mNanoappSubscriptions) {
718 debugDump.print(" nappID=%" PRIu16 " sub ID=%" PRIu32 "\n",
719 sub.nanoappInstanceId, sub.subscriptionId);
720 }
721 }
722
723 if (!mPendingNanSubscribeRequests.empty()) {
724 debugDump.print(" Pending NAN service subscriptions:\n");
725 for (const auto &req : mPendingNanSubscribeRequests) {
726 debugDump.print(" nappID=%" PRIu16 " (type %" PRIu8 ") to svc: %s\n",
727 req.nanoappInstanceId, req.type, req.service.data());
728 }
729 }
730 }
731
scanMonitorIsEnabled() const732 bool WifiRequestManager::scanMonitorIsEnabled() const {
733 return !mScanMonitorNanoapps.empty();
734 }
735
nanoappHasScanMonitorRequest(uint16_t instanceId,size_t * nanoappIndex) const736 bool WifiRequestManager::nanoappHasScanMonitorRequest(
737 uint16_t instanceId, size_t *nanoappIndex) const {
738 size_t index = mScanMonitorNanoapps.find(instanceId);
739 bool hasScanMonitorRequest = (index != mScanMonitorNanoapps.size());
740 if (hasScanMonitorRequest && nanoappIndex != nullptr) {
741 *nanoappIndex = index;
742 }
743
744 return hasScanMonitorRequest;
745 }
746
scanMonitorIsInRequestedState(bool requestedState,bool nanoappHasRequest) const747 bool WifiRequestManager::scanMonitorIsInRequestedState(
748 bool requestedState, bool nanoappHasRequest) const {
749 return (requestedState == scanMonitorIsEnabled() ||
750 (!requestedState &&
751 (!nanoappHasRequest || mScanMonitorNanoapps.size() > 1)));
752 }
753
scanMonitorStateTransitionIsRequired(bool requestedState,bool nanoappHasRequest) const754 bool WifiRequestManager::scanMonitorStateTransitionIsRequired(
755 bool requestedState, bool nanoappHasRequest) const {
756 return ((requestedState && mScanMonitorNanoapps.empty()) ||
757 (!requestedState && nanoappHasRequest &&
758 mScanMonitorNanoapps.size() == 1));
759 }
760
addScanMonitorRequestToQueue(Nanoapp * nanoapp,bool enable,const void * cookie)761 bool WifiRequestManager::addScanMonitorRequestToQueue(Nanoapp *nanoapp,
762 bool enable,
763 const void *cookie) {
764 PendingScanMonitorRequest scanMonitorStateTransition;
765 scanMonitorStateTransition.nanoappInstanceId = nanoapp->getInstanceId();
766 scanMonitorStateTransition.cookie = cookie;
767 scanMonitorStateTransition.enable = enable;
768
769 bool success = mPendingScanMonitorRequests.push(scanMonitorStateTransition);
770 if (!success) {
771 LOGW("Too many scan monitor state transitions");
772 }
773
774 return success;
775 }
776
nanoappHasPendingScanMonitorRequest(uint16_t instanceId) const777 bool WifiRequestManager::nanoappHasPendingScanMonitorRequest(
778 uint16_t instanceId) const {
779 const int numRequests = static_cast<int>(mPendingScanMonitorRequests.size());
780 for (int i = numRequests - 1; i >= 0; i--) {
781 const PendingScanMonitorRequest &request =
782 mPendingScanMonitorRequests[static_cast<size_t>(i)];
783 // The last pending request determines the state of the scan monitoring.
784 if (request.nanoappInstanceId == instanceId) {
785 return request.enable;
786 }
787 }
788
789 return false;
790 }
791
updateNanoappScanMonitoringList(bool enable,uint16_t instanceId)792 bool WifiRequestManager::updateNanoappScanMonitoringList(bool enable,
793 uint16_t instanceId) {
794 bool success = true;
795 Nanoapp *nanoapp =
796 EventLoopManagerSingleton::get()->getEventLoop().findNanoappByInstanceId(
797 instanceId);
798 size_t nanoappIndex;
799 bool hasExistingRequest =
800 nanoappHasScanMonitorRequest(instanceId, &nanoappIndex);
801
802 if (nanoapp == nullptr) {
803 // When the scan monitoring is disabled from inside nanoappEnd() or when
804 // CHRE cleanup the subscription automatically it is possible that the
805 // current method is called after the nanoapp is unloaded. In such a case
806 // we still want to remove the nanoapp from mScanMonitorNanoapps.
807 if (!enable && hasExistingRequest) {
808 mScanMonitorNanoapps.erase(nanoappIndex);
809 } else {
810 LOGW("Failed to update scan monitoring list for non-existent nanoapp");
811 }
812 } else {
813 if (enable) {
814 if (!hasExistingRequest) {
815 // The scan monitor was successfully enabled for this nanoapp and
816 // there is no existing request. Add it to the list of scan monitoring
817 // nanoapps.
818 success = mScanMonitorNanoapps.push_back(instanceId);
819 if (!success) {
820 LOG_OOM();
821 } else {
822 nanoapp->registerForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
823 }
824 }
825 } else if (hasExistingRequest) {
826 // The scan monitor was successfully disabled for a previously enabled
827 // nanoapp. Remove it from the list of scan monitoring nanoapps.
828 mScanMonitorNanoapps.erase(nanoappIndex);
829 nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
830 } // else disabling an inactive request, treat as success per the CHRE API.
831 }
832
833 return success;
834 }
835
postScanMonitorAsyncResultEvent(uint16_t nanoappInstanceId,bool success,bool enable,uint8_t errorCode,const void * cookie)836 bool WifiRequestManager::postScanMonitorAsyncResultEvent(
837 uint16_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
838 const void *cookie) {
839 // Allocate and post an event to the nanoapp requesting wifi.
840 bool eventPosted = false;
841 if (!success || updateNanoappScanMonitoringList(enable, nanoappInstanceId)) {
842 chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
843 if (event == nullptr) {
844 LOG_OOM();
845 } else {
846 event->requestType = CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR;
847 event->success = success;
848 event->errorCode = errorCode;
849 event->reserved = 0;
850 event->cookie = cookie;
851
852 mScanMonitorErrorHistogram[errorCode]++;
853
854 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
855 CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
856 nanoappInstanceId);
857 eventPosted = true;
858 }
859 }
860
861 return eventPosted;
862 }
863
postScanMonitorAsyncResultEventFatal(uint16_t nanoappInstanceId,bool success,bool enable,uint8_t errorCode,const void * cookie)864 void WifiRequestManager::postScanMonitorAsyncResultEventFatal(
865 uint16_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
866 const void *cookie) {
867 if (!postScanMonitorAsyncResultEvent(nanoappInstanceId, success, enable,
868 errorCode, cookie)) {
869 FATAL_ERROR("Failed to send WiFi scan monitor async result event");
870 }
871 }
872
postScanRequestAsyncResultEvent(uint16_t nanoappInstanceId,bool success,uint8_t errorCode,const void * cookie)873 bool WifiRequestManager::postScanRequestAsyncResultEvent(
874 uint16_t nanoappInstanceId, bool success, uint8_t errorCode,
875 const void *cookie) {
876 // TODO: the body of this function can be extracted to a common helper for use
877 // across this function, postScanMonitorAsyncResultEvent,
878 // postRangingAsyncResult, and GnssSession::postAsyncResultEvent
879 bool eventPosted = false;
880 chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
881 if (event == nullptr) {
882 LOG_OOM();
883 } else {
884 event->requestType = CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN;
885 event->success = success;
886 event->errorCode = errorCode;
887 event->reserved = 0;
888 event->cookie = cookie;
889
890 mActiveScanErrorHistogram[errorCode]++;
891
892 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
893 CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
894 nanoappInstanceId);
895 eventPosted = true;
896 }
897
898 return eventPosted;
899 }
900
postScanRequestAsyncResultEventFatal(uint16_t nanoappInstanceId,bool success,uint8_t errorCode,const void * cookie)901 void WifiRequestManager::postScanRequestAsyncResultEventFatal(
902 uint16_t nanoappInstanceId, bool success, uint8_t errorCode,
903 const void *cookie) {
904 if (!postScanRequestAsyncResultEvent(nanoappInstanceId, success, errorCode,
905 cookie)) {
906 FATAL_ERROR("Failed to send WiFi scan request async result event");
907 }
908 }
909
postScanEventFatal(chreWifiScanEvent * event)910 void WifiRequestManager::postScanEventFatal(chreWifiScanEvent *event) {
911 mLastScanEventTime = Milliseconds(SystemTime::getMonotonicTime());
912 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
913 CHRE_EVENT_WIFI_SCAN_RESULT, event, freeWifiScanEventCallback);
914 }
915
handleScanMonitorStateChangeSync(bool enabled,uint8_t errorCode)916 void WifiRequestManager::handleScanMonitorStateChangeSync(bool enabled,
917 uint8_t errorCode) {
918 // Success is defined as having no errors ... in life ༼ つ ◕_◕ ༽つ
919 bool success = (errorCode == CHRE_ERROR_NONE);
920
921 // TODO(b/62904616): re-enable this assertion
922 // CHRE_ASSERT_LOG(!mScanMonitorStateTransitions.empty(),
923 // "handleScanMonitorStateChangeSync called with no
924 // transitions");
925 if (mPendingScanMonitorRequests.empty()) {
926 LOGE(
927 "WiFi PAL error: handleScanMonitorStateChangeSync called with no "
928 "transitions (enabled %d errorCode %" PRIu8 ")",
929 enabled, errorCode);
930 }
931
932 // Always check the front of the queue.
933 if (!mPendingScanMonitorRequests.empty()) {
934 const auto &stateTransition = mPendingScanMonitorRequests.front();
935 success &= (stateTransition.enable == enabled);
936 postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
937 success, stateTransition.enable,
938 errorCode, stateTransition.cookie);
939 mPendingScanMonitorRequests.pop();
940 }
941
942 dispatchQueuedConfigureScanMonitorRequests();
943 }
944
postNanAsyncResultEvent(uint16_t nanoappInstanceId,uint8_t requestType,bool success,uint8_t errorCode,const void * cookie)945 void WifiRequestManager::postNanAsyncResultEvent(uint16_t nanoappInstanceId,
946 uint8_t requestType,
947 bool success,
948 uint8_t errorCode,
949 const void *cookie) {
950 chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
951 if (event == nullptr) {
952 LOG_OOM();
953 } else {
954 event->requestType = requestType;
955 event->cookie = cookie;
956 event->errorCode = errorCode;
957 event->success = success;
958
959 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
960 CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
961 nanoappInstanceId);
962 }
963 }
964
handleScanResponseSync(bool pending,uint8_t errorCode)965 void WifiRequestManager::handleScanResponseSync(bool pending,
966 uint8_t errorCode) {
967 // TODO(b/65206783): re-enable this assertion
968 // CHRE_ASSERT_LOG(mPendingScanRequests.empty(),
969 // "handleScanResponseSync called with no outstanding
970 // request");
971 if (mPendingScanRequests.empty()) {
972 LOGE("handleScanResponseSync called with no outstanding request");
973 }
974
975 if (mScanRequestTimeoutHandle != CHRE_TIMER_INVALID) {
976 EventLoopManagerSingleton::get()->cancelDelayedCallback(
977 mScanRequestTimeoutHandle);
978 mScanRequestTimeoutHandle = CHRE_TIMER_INVALID;
979 }
980
981 // TODO: raise this to CHRE_ASSERT_LOG
982 if (!pending && errorCode == CHRE_ERROR_NONE) {
983 LOGE("Invalid wifi scan response");
984 errorCode = CHRE_ERROR;
985 }
986
987 if (!mPendingScanRequests.empty()) {
988 bool success = (pending && errorCode == CHRE_ERROR_NONE);
989 if (!success) {
990 LOGW("Wifi scan request failed: pending %d, errorCode %" PRIu8, pending,
991 errorCode);
992 }
993 PendingScanRequest ¤tScanRequest = mPendingScanRequests.front();
994 postScanRequestAsyncResultEventFatal(currentScanRequest.nanoappInstanceId,
995 success, errorCode,
996 currentScanRequest.cookie);
997
998 // Set a flag to indicate that results may be pending.
999 mScanRequestResultsArePending = pending;
1000
1001 if (pending) {
1002 Nanoapp *nanoapp =
1003 EventLoopManagerSingleton::get()
1004 ->getEventLoop()
1005 .findNanoappByInstanceId(currentScanRequest.nanoappInstanceId);
1006 if (nanoapp == nullptr) {
1007 LOGW("Received WiFi scan response for unknown nanoapp");
1008 } else {
1009 nanoapp->registerForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
1010 }
1011 } else {
1012 // If the scan results are not pending, pop the first event since it's no
1013 // longer waiting for anything. Otherwise, wait for the results to be
1014 // delivered and then pop the first request.
1015 mPendingScanRequests.pop();
1016 dispatchQueuedScanRequests(true /* postAsyncResult */);
1017 }
1018 }
1019 }
1020
postRangingAsyncResult(uint8_t errorCode)1021 bool WifiRequestManager::postRangingAsyncResult(uint8_t errorCode) {
1022 bool eventPosted = false;
1023
1024 if (mPendingRangingRequests.empty()) {
1025 LOGE("Unexpected ranging event callback");
1026 } else {
1027 auto *event = memoryAlloc<struct chreAsyncResult>();
1028 if (event == nullptr) {
1029 LOG_OOM();
1030 } else {
1031 const PendingRangingRequest &req = mPendingRangingRequests.front();
1032
1033 event->requestType = CHRE_WIFI_REQUEST_TYPE_RANGING;
1034 event->success = (errorCode == CHRE_ERROR_NONE);
1035 event->errorCode = errorCode;
1036 event->reserved = 0;
1037 event->cookie = req.cookie;
1038
1039 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
1040 CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
1041 req.nanoappInstanceId);
1042 eventPosted = true;
1043 }
1044 }
1045
1046 return eventPosted;
1047 }
1048
dispatchQueuedRangingRequest()1049 bool WifiRequestManager::dispatchQueuedRangingRequest() {
1050 bool success = false;
1051 uint8_t asyncError = CHRE_ERROR_NONE;
1052 PendingRangingRequest &req = mPendingRangingRequests.front();
1053
1054 if (!areRequiredSettingsEnabled()) {
1055 asyncError = CHRE_ERROR_FUNCTION_DISABLED;
1056 } else if (!sendRangingRequest(req)) {
1057 asyncError = CHRE_ERROR;
1058 } else {
1059 success = true;
1060 }
1061
1062 if (asyncError != CHRE_ERROR_NONE) {
1063 postRangingAsyncResult(asyncError);
1064 mPendingRangingRequests.pop();
1065 }
1066
1067 return success;
1068 }
1069
dispatchQueuedNanSubscribeRequest()1070 bool WifiRequestManager::dispatchQueuedNanSubscribeRequest() {
1071 bool success = false;
1072
1073 if (!mPendingNanSubscribeRequests.empty()) {
1074 uint8_t asyncError = CHRE_ERROR_NONE;
1075 const auto &req = mPendingNanSubscribeRequests.front();
1076 struct chreWifiNanSubscribeConfig config = {};
1077 buildNanSubscribeConfigFromRequest(req, &config);
1078
1079 if (!areRequiredSettingsEnabled()) {
1080 asyncError = CHRE_ERROR_FUNCTION_DISABLED;
1081 } else if (!mPlatformWifi.nanSubscribe(&config)) {
1082 asyncError = CHRE_ERROR;
1083 }
1084
1085 if (asyncError != CHRE_ERROR_NONE) {
1086 postNanAsyncResultEvent(req.nanoappInstanceId,
1087 CHRE_WIFI_REQUEST_TYPE_NAN_SUBSCRIBE,
1088 false /*success*/, asyncError, req.cookie);
1089 mPendingNanSubscribeRequests.pop();
1090 } else {
1091 success = true;
1092 }
1093 }
1094 return success;
1095 }
1096
dispatchQueuedNanSubscribeRequestWithRetry()1097 void WifiRequestManager::dispatchQueuedNanSubscribeRequestWithRetry() {
1098 while (!mPendingNanSubscribeRequests.empty() &&
1099 !dispatchQueuedNanSubscribeRequest())
1100 ;
1101 }
1102
dispatchQueuedScanRequests(bool postAsyncResult)1103 bool WifiRequestManager::dispatchQueuedScanRequests(bool postAsyncResult) {
1104 while (!mPendingScanRequests.empty()) {
1105 uint8_t asyncError = CHRE_ERROR_NONE;
1106 const PendingScanRequest ¤tScanRequest = mPendingScanRequests.front();
1107
1108 if (!EventLoopManagerSingleton::get()
1109 ->getSettingManager()
1110 .getSettingEnabled(Setting::WIFI_AVAILABLE)) {
1111 asyncError = CHRE_ERROR_FUNCTION_DISABLED;
1112 } else if (!mPlatformWifi.requestScan(¤tScanRequest.scanParams)) {
1113 asyncError = CHRE_ERROR;
1114 } else {
1115 mScanRequestTimeoutHandle = setScanRequestTimer();
1116 return true;
1117 }
1118
1119 if (postAsyncResult) {
1120 postScanRequestAsyncResultEvent(currentScanRequest.nanoappInstanceId,
1121 false /*success*/, asyncError,
1122 currentScanRequest.cookie);
1123 } else {
1124 LOGE("Wifi scan request failed");
1125 }
1126 mPendingScanRequests.pop();
1127 }
1128 return false;
1129 }
1130
handleRangingEventSync(uint8_t errorCode,struct chreWifiRangingEvent * event)1131 void WifiRequestManager::handleRangingEventSync(
1132 uint8_t errorCode, struct chreWifiRangingEvent *event) {
1133 if (!areRequiredSettingsEnabled()) {
1134 errorCode = CHRE_ERROR_FUNCTION_DISABLED;
1135 }
1136
1137 if (postRangingAsyncResult(errorCode)) {
1138 if (errorCode != CHRE_ERROR_NONE) {
1139 LOGW("RTT ranging failed with error %d", errorCode);
1140 if (event != nullptr) {
1141 freeWifiRangingEventCallback(CHRE_EVENT_WIFI_RANGING_RESULT, event);
1142 }
1143 } else {
1144 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
1145 CHRE_EVENT_WIFI_RANGING_RESULT, event, freeWifiRangingEventCallback,
1146 mPendingRangingRequests.front().nanoappInstanceId);
1147 }
1148 mPendingRangingRequests.pop();
1149 }
1150
1151 // If we have any pending requests, try issuing them to the platform until the
1152 // first one succeeds.
1153 while (!mPendingRangingRequests.empty() && !dispatchQueuedRangingRequest())
1154 ;
1155 }
1156
handleFreeWifiScanEvent(chreWifiScanEvent * scanEvent)1157 void WifiRequestManager::handleFreeWifiScanEvent(chreWifiScanEvent *scanEvent) {
1158 if (mScanRequestResultsArePending) {
1159 // Reset the event distribution logic once an entire scan event has been
1160 // received and processed by the nanoapp requesting the scan event.
1161 mScanEventResultCountAccumulator += scanEvent->resultCount;
1162 if (mScanEventResultCountAccumulator >= scanEvent->resultTotal) {
1163 mScanEventResultCountAccumulator = 0;
1164 mScanRequestResultsArePending = false;
1165 }
1166
1167 if (!mScanRequestResultsArePending && !mPendingScanRequests.empty()) {
1168 uint16_t pendingNanoappInstanceId =
1169 mPendingScanRequests.front().nanoappInstanceId;
1170 Nanoapp *nanoapp = EventLoopManagerSingleton::get()
1171 ->getEventLoop()
1172 .findNanoappByInstanceId(pendingNanoappInstanceId);
1173 if (nanoapp == nullptr) {
1174 LOGW("Attempted to unsubscribe unknown nanoapp from WiFi scan events");
1175 } else if (!nanoappHasScanMonitorRequest(pendingNanoappInstanceId)) {
1176 nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
1177 }
1178 mPendingScanRequests.pop();
1179 dispatchQueuedScanRequests(true /* postAsyncResult */);
1180 }
1181 }
1182
1183 mPlatformWifi.releaseScanEvent(scanEvent);
1184 }
1185
addWifiScanRequestLog(uint16_t nanoappInstanceId,const chreWifiScanParams * params)1186 void WifiRequestManager::addWifiScanRequestLog(
1187 uint16_t nanoappInstanceId, const chreWifiScanParams *params) {
1188 mWifiScanRequestLogs.kick_push(
1189 WifiScanRequestLog(SystemTime::getMonotonicTime(), nanoappInstanceId,
1190 static_cast<chreWifiScanType>(params->scanType),
1191 static_cast<Milliseconds>(params->maxScanAgeMs)));
1192 }
1193
freeWifiScanEventCallback(uint16_t,void * eventData)1194 void WifiRequestManager::freeWifiScanEventCallback(uint16_t /* eventType */,
1195 void *eventData) {
1196 auto *scanEvent = static_cast<struct chreWifiScanEvent *>(eventData);
1197 EventLoopManagerSingleton::get()
1198 ->getWifiRequestManager()
1199 .handleFreeWifiScanEvent(scanEvent);
1200 }
1201
freeWifiRangingEventCallback(uint16_t,void * eventData)1202 void WifiRequestManager::freeWifiRangingEventCallback(uint16_t /* eventType */,
1203 void *eventData) {
1204 auto *event = static_cast<struct chreWifiRangingEvent *>(eventData);
1205 EventLoopManagerSingleton::get()
1206 ->getWifiRequestManager()
1207 .mPlatformWifi.releaseRangingEvent(event);
1208 }
1209
freeNanDiscoveryEventCallback(uint16_t,void * eventData)1210 void WifiRequestManager::freeNanDiscoveryEventCallback(uint16_t /* eventType */,
1211 void *eventData) {
1212 auto *event = static_cast<struct chreWifiNanDiscoveryEvent *>(eventData);
1213 EventLoopManagerSingleton::get()
1214 ->getWifiRequestManager()
1215 .mPlatformWifi.releaseNanDiscoveryEvent(event);
1216 }
1217
nanSubscribe(Nanoapp * nanoapp,const struct chreWifiNanSubscribeConfig * config,const void * cookie)1218 bool WifiRequestManager::nanSubscribe(
1219 Nanoapp *nanoapp, const struct chreWifiNanSubscribeConfig *config,
1220 const void *cookie) {
1221 CHRE_ASSERT(nanoapp);
1222
1223 bool success = false;
1224
1225 if (!areRequiredSettingsEnabled()) {
1226 success = true;
1227 postNanAsyncResultEvent(
1228 nanoapp->getInstanceId(), CHRE_WIFI_REQUEST_TYPE_NAN_SUBSCRIBE,
1229 false /*success*/, CHRE_ERROR_FUNCTION_DISABLED, cookie);
1230 } else {
1231 if (!mPendingNanSubscribeRequests.emplace()) {
1232 LOG_OOM();
1233 } else {
1234 auto &req = mPendingNanSubscribeRequests.back();
1235 req.nanoappInstanceId = nanoapp->getInstanceId();
1236 req.cookie = cookie;
1237 if (!copyNanSubscribeConfigToRequest(req, config)) {
1238 LOG_OOM();
1239 }
1240
1241 if (mNanIsAvailable) {
1242 if (mPendingNanSubscribeRequests.size() == 1) {
1243 // First in line; dispatch request immediately.
1244 success = mPlatformWifi.nanSubscribe(config);
1245 if (!success) {
1246 mPendingNanSubscribeRequests.pop_back();
1247 }
1248 } else {
1249 success = true;
1250 }
1251 } else {
1252 success = true;
1253 sendNanConfiguration(true /*enable*/);
1254 }
1255 }
1256 }
1257 return success;
1258 }
1259
nanSubscribeCancel(Nanoapp * nanoapp,uint32_t subscriptionId)1260 bool WifiRequestManager::nanSubscribeCancel(Nanoapp *nanoapp,
1261 uint32_t subscriptionId) {
1262 bool success = false;
1263 for (size_t i = 0; i < mNanoappSubscriptions.size(); ++i) {
1264 if (mNanoappSubscriptions[i].subscriptionId == subscriptionId &&
1265 mNanoappSubscriptions[i].nanoappInstanceId ==
1266 nanoapp->getInstanceId()) {
1267 success = mPlatformWifi.nanSubscribeCancel(subscriptionId);
1268 break;
1269 }
1270 }
1271
1272 if (!success) {
1273 LOGE("Failed to cancel subscription %" PRIu32 " for napp %" PRIu16,
1274 subscriptionId, nanoapp->getInstanceId());
1275 }
1276
1277 return success;
1278 }
1279
copyNanSubscribeConfigToRequest(PendingNanSubscribeRequest & req,const struct chreWifiNanSubscribeConfig * config)1280 bool WifiRequestManager::copyNanSubscribeConfigToRequest(
1281 PendingNanSubscribeRequest &req,
1282 const struct chreWifiNanSubscribeConfig *config) {
1283 bool success = false;
1284 req.type = config->subscribeType;
1285
1286 if (req.service.copy_array(config->service,
1287 std::strlen(config->service) + 1) &&
1288 req.serviceSpecificInfo.copy_array(config->serviceSpecificInfo,
1289 config->serviceSpecificInfoSize) &&
1290 req.matchFilter.copy_array(config->matchFilter,
1291 config->matchFilterLength)) {
1292 success = true;
1293 } else {
1294 LOG_OOM();
1295 }
1296
1297 return success;
1298 }
1299
buildNanSubscribeConfigFromRequest(const PendingNanSubscribeRequest & req,struct chreWifiNanSubscribeConfig * config)1300 void WifiRequestManager::buildNanSubscribeConfigFromRequest(
1301 const PendingNanSubscribeRequest &req,
1302 struct chreWifiNanSubscribeConfig *config) {
1303 config->subscribeType = req.type;
1304 config->service = req.service.data();
1305 config->serviceSpecificInfo = req.serviceSpecificInfo.data();
1306 config->serviceSpecificInfoSize =
1307 static_cast<uint32_t>(req.serviceSpecificInfo.size());
1308 config->matchFilter = req.matchFilter.data();
1309 config->matchFilterLength = static_cast<uint32_t>(req.matchFilter.size());
1310 }
1311
areRequiredSettingsEnabled()1312 inline bool WifiRequestManager::areRequiredSettingsEnabled() {
1313 SettingManager &settingManager =
1314 EventLoopManagerSingleton::get()->getSettingManager();
1315 return settingManager.getSettingEnabled(Setting::LOCATION) &&
1316 settingManager.getSettingEnabled(Setting::WIFI_AVAILABLE);
1317 }
1318
cancelNanSubscriptionsAndInformNanoapps()1319 void WifiRequestManager::cancelNanSubscriptionsAndInformNanoapps() {
1320 for (size_t i = 0; i < mNanoappSubscriptions.size(); ++i) {
1321 chreWifiNanSessionTerminatedEvent *event =
1322 memoryAlloc<chreWifiNanSessionTerminatedEvent>();
1323 if (event == nullptr) {
1324 LOG_OOM();
1325 } else {
1326 event->id = mNanoappSubscriptions[i].subscriptionId;
1327 event->reason = CHRE_ERROR_FUNCTION_DISABLED;
1328 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
1329 CHRE_EVENT_WIFI_NAN_SESSION_TERMINATED, event, freeEventDataCallback,
1330 mNanoappSubscriptions[i].nanoappInstanceId);
1331 }
1332 }
1333 mNanoappSubscriptions.clear();
1334 }
1335
cancelNanPendingRequestsAndInformNanoapps()1336 void WifiRequestManager::cancelNanPendingRequestsAndInformNanoapps() {
1337 for (size_t i = 0; i < mPendingNanSubscribeRequests.size(); ++i) {
1338 auto &req = mPendingNanSubscribeRequests[i];
1339 chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
1340 if (event == nullptr) {
1341 LOG_OOM();
1342 break;
1343 } else {
1344 event->requestType = CHRE_WIFI_REQUEST_TYPE_NAN_SUBSCRIBE;
1345 event->success = false;
1346 event->errorCode = CHRE_ERROR_FUNCTION_DISABLED;
1347 event->cookie = req.cookie;
1348 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
1349 CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
1350 req.nanoappInstanceId);
1351 }
1352 }
1353 mPendingNanSubscribeRequests.clear();
1354 }
1355
handleNanAvailabilitySync(bool available)1356 void WifiRequestManager::handleNanAvailabilitySync(bool available) {
1357 PendingNanConfigType nanState =
1358 available ? PendingNanConfigType::ENABLE : PendingNanConfigType::DISABLE;
1359 mNanIsAvailable = available;
1360
1361 if (nanState == mNanConfigRequestToHostPendingType) {
1362 mNanConfigRequestToHostPending = false;
1363 mNanConfigRequestToHostPendingType = PendingNanConfigType::UNKNOWN;
1364 }
1365
1366 if (available) {
1367 dispatchQueuedNanSubscribeRequestWithRetry();
1368 } else {
1369 cancelNanPendingRequestsAndInformNanoapps();
1370 cancelNanSubscriptionsAndInformNanoapps();
1371 }
1372 }
1373
updateNanAvailability(bool available)1374 void WifiRequestManager::updateNanAvailability(bool available) {
1375 auto callback = [](uint16_t /*type*/, void *data, void * /*extraData*/) {
1376 bool cbAvail = NestedDataPtr<bool>(data);
1377 EventLoopManagerSingleton::get()
1378 ->getWifiRequestManager()
1379 .handleNanAvailabilitySync(cbAvail);
1380 };
1381
1382 EventLoopManagerSingleton::get()->deferCallback(
1383 SystemCallbackType::WifiNanAvailabilityEvent,
1384 NestedDataPtr<bool>(available), callback);
1385 }
1386
sendNanConfiguration(bool enable)1387 void WifiRequestManager::sendNanConfiguration(bool enable) {
1388 PendingNanConfigType requiredState =
1389 enable ? PendingNanConfigType::ENABLE : PendingNanConfigType::DISABLE;
1390 if (!mNanConfigRequestToHostPending ||
1391 (mNanConfigRequestToHostPendingType != requiredState)) {
1392 mNanConfigRequestToHostPending = true;
1393 mNanConfigRequestToHostPendingType = requiredState;
1394 EventLoopManagerSingleton::get()
1395 ->getHostCommsManager()
1396 .sendNanConfiguration(enable);
1397 }
1398 }
1399
onSettingChanged(Setting setting,bool enabled)1400 void WifiRequestManager::onSettingChanged(Setting setting, bool enabled) {
1401 if ((setting == Setting::WIFI_AVAILABLE) && !enabled) {
1402 cancelNanPendingRequestsAndInformNanoapps();
1403 cancelNanSubscriptionsAndInformNanoapps();
1404 }
1405 }
1406
1407 } // namespace chre
1408