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(&params);
234   } else {
235     struct chreWifiNanRangingParams params;
236     std::memcpy(params.macAddress, request.nanRangingParams.macAddress,
237                 CHRE_WIFI_BSSID_LEN);
238     success = mPlatformWifi.requestNanRanging(&params);
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(&paramsCompat, params, offsetof(chreWifiScanParams, radioChainPref));
355     paramsCompat.radioChainPref = CHRE_WIFI_RADIO_CHAIN_PREF_DEFAULT;
356     params = &paramsCompat;
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 &currentScanRequest = 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 &currentScanRequest = 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(&currentScanRequest.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