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