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