wifi_request_manager.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  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. #include <cinttypes>
  17. #include <cstddef>
  18. #include <cstring>
  19. #include "chre/core/event_loop_manager.h"
  20. #include "chre/core/wifi_request_manager.h"
  21. #include "chre/platform/fatal_error.h"
  22. #include "chre/platform/log.h"
  23. #include "chre/platform/system_time.h"
  24. #include "chre/util/system/debug_dump.h"
  25. #include "chre_api/chre/version.h"
  26. namespace chre {
  27. WifiRequestManager::WifiRequestManager() {
  28. // Reserve space for at least one scan monitoring nanoapp. This ensures that
  29. // the first asynchronous push_back will succeed. Future push_backs will be
  30. // synchronous and failures will be returned to the client.
  31. if (!mScanMonitorNanoapps.reserve(1)) {
  32. FATAL_ERROR_OOM();
  33. }
  34. }
  35. void WifiRequestManager::init() {
  36. mPlatformWifi.init();
  37. }
  38. uint32_t WifiRequestManager::getCapabilities() {
  39. return mPlatformWifi.getCapabilities();
  40. }
  41. bool WifiRequestManager::configureScanMonitor(Nanoapp *nanoapp, bool enable,
  42. const void *cookie) {
  43. CHRE_ASSERT(nanoapp);
  44. bool success = false;
  45. uint32_t instanceId = nanoapp->getInstanceId();
  46. bool hasScanMonitorRequest = nanoappHasScanMonitorRequest(instanceId);
  47. if (!mPendingScanMonitorRequests.empty()) {
  48. success = addScanMonitorRequestToQueue(nanoapp, enable, cookie);
  49. } else if (scanMonitorIsInRequestedState(enable, hasScanMonitorRequest)) {
  50. // The scan monitor is already in the requested state. A success event can
  51. // be posted immediately.
  52. success = postScanMonitorAsyncResultEvent(instanceId, true /* success */,
  53. enable, CHRE_ERROR_NONE, cookie);
  54. } else if (scanMonitorStateTransitionIsRequired(enable,
  55. hasScanMonitorRequest)) {
  56. success = addScanMonitorRequestToQueue(nanoapp, enable, cookie);
  57. if (success) {
  58. success = mPlatformWifi.configureScanMonitor(enable);
  59. if (!success) {
  60. mPendingScanMonitorRequests.pop_back();
  61. LOGE("Failed to enable the scan monitor for nanoapp instance %" PRIu32,
  62. instanceId);
  63. }
  64. }
  65. } else {
  66. CHRE_ASSERT_LOG(false, "Invalid scan monitor configuration");
  67. }
  68. return success;
  69. }
  70. bool WifiRequestManager::requestRanging(
  71. Nanoapp *nanoapp, const struct chreWifiRangingParams *params,
  72. const void *cookie) {
  73. CHRE_ASSERT(nanoapp);
  74. bool success = false;
  75. if (!mPendingRangingRequests.emplace()) {
  76. LOGE("Can't issue new RTT request; pending queue full");
  77. } else {
  78. PendingRangingRequest& req = mPendingRangingRequests.back();
  79. req.nanoappInstanceId = nanoapp->getInstanceId();
  80. req.cookie = cookie;
  81. if (mPendingRangingRequests.size() == 1) {
  82. // First in line; dispatch request immediately
  83. success = mPlatformWifi.requestRanging(params);
  84. if (!success) {
  85. LOGE("WiFi RTT request failed");
  86. mPendingRangingRequests.pop_back();
  87. } else {
  88. mRangingResponseTimeout = SystemTime::getMonotonicTime()
  89. + Nanoseconds(CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS);
  90. }
  91. } else {
  92. // Dispatch request later, after prior requests finish
  93. // TODO(b/65331248): use a timer to ensure the platform is meeting its
  94. // contract
  95. CHRE_ASSERT_LOG(SystemTime::getMonotonicTime() <= mRangingResponseTimeout,
  96. "WiFi platform didn't give callback in time");
  97. success = req.targetList.copy_array(params->targetList,
  98. params->targetListLen);
  99. if (!success) {
  100. LOG_OOM();
  101. mPendingRangingRequests.pop_back();
  102. }
  103. }
  104. }
  105. return success;
  106. }
  107. bool WifiRequestManager::requestScan(Nanoapp *nanoapp,
  108. const struct chreWifiScanParams *params,
  109. const void *cookie) {
  110. CHRE_ASSERT(nanoapp);
  111. // TODO(b/65331248): replace with a timer to actively check response timeout
  112. bool timedOut = (mScanRequestingNanoappInstanceId.has_value()
  113. && mLastScanRequestTime
  114. + Nanoseconds(CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS)
  115. < SystemTime::getMonotonicTime());
  116. if (timedOut) {
  117. LOGE("Scan request async response timed out");
  118. mScanRequestingNanoappInstanceId.reset();
  119. }
  120. // Handle compatibility with nanoapps compiled against API v1.1, which doesn't
  121. // include the radioChainPref parameter in chreWifiScanParams
  122. struct chreWifiScanParams paramsCompat;
  123. if (nanoapp->getTargetApiVersion() < CHRE_API_VERSION_1_2) {
  124. memcpy(&paramsCompat, params, offsetof(chreWifiScanParams, radioChainPref));
  125. paramsCompat.radioChainPref = CHRE_WIFI_RADIO_CHAIN_PREF_DEFAULT;
  126. params = &paramsCompat;
  127. }
  128. bool success = false;
  129. if (mScanRequestingNanoappInstanceId.has_value()) {
  130. LOGE("Active wifi scan request made while a request is in flight");
  131. } else {
  132. success = mPlatformWifi.requestScan(params);
  133. if (!success) {
  134. LOGE("Wifi scan request failed");
  135. } else {
  136. mScanRequestingNanoappInstanceId = nanoapp->getInstanceId();
  137. mScanRequestingNanoappCookie = cookie;
  138. mLastScanRequestTime = SystemTime::getMonotonicTime();
  139. }
  140. }
  141. return success;
  142. }
  143. void WifiRequestManager::handleScanMonitorStateChange(bool enabled,
  144. uint8_t errorCode) {
  145. struct CallbackState {
  146. bool enabled;
  147. uint8_t errorCode;
  148. };
  149. auto *cbState = memoryAlloc<CallbackState>();
  150. if (cbState == nullptr) {
  151. LOG_OOM();
  152. } else {
  153. cbState->enabled = enabled;
  154. cbState->errorCode = errorCode;
  155. auto callback = [](uint16_t /* eventType */, void *eventData) {
  156. auto *state = static_cast<CallbackState *>(eventData);
  157. EventLoopManagerSingleton::get()->getWifiRequestManager()
  158. .handleScanMonitorStateChangeSync(state->enabled, state->errorCode);
  159. memoryFree(state);
  160. };
  161. EventLoopManagerSingleton::get()->deferCallback(
  162. SystemCallbackType::WifiScanMonitorStateChange, cbState, callback);
  163. }
  164. }
  165. void WifiRequestManager::handleScanResponse(bool pending,
  166. uint8_t errorCode) {
  167. struct CallbackState {
  168. bool pending;
  169. uint8_t errorCode;
  170. };
  171. auto *cbState = memoryAlloc<CallbackState>();
  172. if (cbState == nullptr) {
  173. LOG_OOM();
  174. } else {
  175. cbState->pending = pending;
  176. cbState->errorCode = errorCode;
  177. auto callback = [](uint16_t /* eventType */, void *eventData) {
  178. auto *state = static_cast<CallbackState *>(eventData);
  179. EventLoopManagerSingleton::get()->getWifiRequestManager()
  180. .handleScanResponseSync(state->pending, state->errorCode);
  181. memoryFree(state);
  182. };
  183. EventLoopManagerSingleton::get()->deferCallback(
  184. SystemCallbackType::WifiRequestScanResponse, cbState, callback);
  185. }
  186. }
  187. void WifiRequestManager::handleRangingEvent(
  188. uint8_t errorCode, struct chreWifiRangingEvent *event) {
  189. // Use two different callbacks to avoid needing a temporary allocation to
  190. // carry the error code into the event loop context
  191. if (errorCode != CHRE_ERROR_NONE) {
  192. // Enables passing the error code through the event data pointer to avoid
  193. // allocating memory
  194. union NestedErrorCode {
  195. void *eventData;
  196. uint8_t errorCode;
  197. };
  198. auto errorCb = [](uint16_t /* eventType */, void *eventData) {
  199. NestedErrorCode cbErrorCode;
  200. cbErrorCode.eventData = eventData;
  201. EventLoopManagerSingleton::get()->getWifiRequestManager()
  202. .handleRangingEventSync(cbErrorCode.errorCode, nullptr);
  203. };
  204. NestedErrorCode error = {};
  205. error.errorCode = errorCode;
  206. EventLoopManagerSingleton::get()->deferCallback(
  207. SystemCallbackType::WifiHandleFailedRanging, error.eventData, errorCb);
  208. } else {
  209. auto successCb = [](uint16_t /* eventType */, void *eventData) {
  210. auto *rttEvent = static_cast<struct chreWifiRangingEvent *>(eventData);
  211. EventLoopManagerSingleton::get()->getWifiRequestManager()
  212. .handleRangingEventSync(CHRE_ERROR_NONE, rttEvent);
  213. };
  214. EventLoopManagerSingleton::get()->deferCallback(
  215. SystemCallbackType::WifiHandleRangingEvent, event, successCb);
  216. }
  217. }
  218. void WifiRequestManager::handleScanEvent(chreWifiScanEvent *event) {
  219. auto callback = [](uint16_t eventType, void *eventData) {
  220. chreWifiScanEvent *scanEvent = static_cast<chreWifiScanEvent *>(eventData);
  221. EventLoopManagerSingleton::get()->getWifiRequestManager()
  222. .postScanEventFatal(scanEvent);
  223. };
  224. EventLoopManagerSingleton::get()->deferCallback(
  225. SystemCallbackType::WifiHandleScanEvent, event, callback);
  226. }
  227. void WifiRequestManager::logStateToBuffer(char *buffer, size_t *bufferPos,
  228. size_t bufferSize) const {
  229. debugDumpPrint(buffer, bufferPos, bufferSize,
  230. "\nWifi: scan monitor %s\n",
  231. scanMonitorIsEnabled() ? "enabled" : "disabled");
  232. debugDumpPrint(buffer, bufferPos, bufferSize,
  233. " Wifi scan monitor enabled nanoapps:\n");
  234. for (const auto& instanceId : mScanMonitorNanoapps) {
  235. debugDumpPrint(buffer, bufferPos, bufferSize,
  236. " nanoappId=%" PRIu32 "\n", instanceId);
  237. }
  238. if (mScanRequestingNanoappInstanceId.has_value()) {
  239. debugDumpPrint(buffer, bufferPos, bufferSize,
  240. " Wifi request pending nanoappId=%" PRIu32 "\n",
  241. mScanRequestingNanoappInstanceId.value());
  242. }
  243. debugDumpPrint(buffer, bufferPos, bufferSize,
  244. " Wifi transition queue:\n");
  245. for (const auto& transition : mPendingScanMonitorRequests) {
  246. debugDumpPrint(buffer, bufferPos, bufferSize,
  247. " enable=%s nanoappId=%" PRIu32 "\n",
  248. transition.enable ? "true" : "false",
  249. transition.nanoappInstanceId);
  250. }
  251. }
  252. bool WifiRequestManager::scanMonitorIsEnabled() const {
  253. return !mScanMonitorNanoapps.empty();
  254. }
  255. bool WifiRequestManager::nanoappHasScanMonitorRequest(
  256. uint32_t instanceId, size_t *nanoappIndex) const {
  257. size_t index = mScanMonitorNanoapps.find(instanceId);
  258. bool hasScanMonitorRequest = (index != mScanMonitorNanoapps.size());
  259. if (hasScanMonitorRequest && nanoappIndex != nullptr) {
  260. *nanoappIndex = index;
  261. }
  262. return hasScanMonitorRequest;
  263. }
  264. bool WifiRequestManager::scanMonitorIsInRequestedState(
  265. bool requestedState, bool nanoappHasRequest) const {
  266. return (requestedState == scanMonitorIsEnabled() || (!requestedState
  267. && (!nanoappHasRequest || mScanMonitorNanoapps.size() > 1)));
  268. }
  269. bool WifiRequestManager::scanMonitorStateTransitionIsRequired(
  270. bool requestedState, bool nanoappHasRequest) const {
  271. return ((requestedState && mScanMonitorNanoapps.empty())
  272. || (!requestedState && nanoappHasRequest
  273. && mScanMonitorNanoapps.size() == 1));
  274. }
  275. bool WifiRequestManager::addScanMonitorRequestToQueue(Nanoapp *nanoapp,
  276. bool enable,
  277. const void *cookie) {
  278. PendingScanMonitorRequest scanMonitorStateTransition;
  279. scanMonitorStateTransition.nanoappInstanceId = nanoapp->getInstanceId();
  280. scanMonitorStateTransition.cookie = cookie;
  281. scanMonitorStateTransition.enable = enable;
  282. bool success = mPendingScanMonitorRequests.push(scanMonitorStateTransition);
  283. if (!success) {
  284. LOGW("Too many scan monitor state transitions");
  285. }
  286. return success;
  287. }
  288. bool WifiRequestManager::updateNanoappScanMonitoringList(bool enable,
  289. uint32_t instanceId) {
  290. bool success = true;
  291. Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
  292. .findNanoappByInstanceId(instanceId);
  293. if (nanoapp == nullptr) {
  294. LOGW("Failed to update scan monitoring list for non-existent nanoapp");
  295. } else {
  296. size_t nanoappIndex;
  297. bool hasExistingRequest = nanoappHasScanMonitorRequest(instanceId,
  298. &nanoappIndex);
  299. if (enable) {
  300. if (!hasExistingRequest) {
  301. // The scan monitor was successfully enabled for this nanoapp and
  302. // there is no existing request. Add it to the list of scan monitoring
  303. // nanoapps.
  304. success = mScanMonitorNanoapps.push_back(instanceId);
  305. if (!success) {
  306. LOG_OOM();
  307. } else {
  308. nanoapp->registerForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
  309. }
  310. }
  311. } else if (hasExistingRequest) {
  312. // The scan monitor was successfully disabled for a previously enabled
  313. // nanoapp. Remove it from the list of scan monitoring nanoapps.
  314. mScanMonitorNanoapps.erase(nanoappIndex);
  315. nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
  316. } // else disabling an inactive request, treat as success per the CHRE API.
  317. }
  318. return success;
  319. }
  320. bool WifiRequestManager::postScanMonitorAsyncResultEvent(
  321. uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
  322. const void *cookie) {
  323. // Allocate and post an event to the nanoapp requesting wifi.
  324. bool eventPosted = false;
  325. if (!success || updateNanoappScanMonitoringList(enable, nanoappInstanceId)) {
  326. chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
  327. if (event == nullptr) {
  328. LOG_OOM();
  329. } else {
  330. event->requestType = CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR;
  331. event->success = success;
  332. event->errorCode = errorCode;
  333. event->reserved = 0;
  334. event->cookie = cookie;
  335. // Post the event.
  336. eventPosted =
  337. EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
  338. CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
  339. nanoappInstanceId);
  340. if (!eventPosted) {
  341. memoryFree(event);
  342. }
  343. }
  344. }
  345. return eventPosted;
  346. }
  347. void WifiRequestManager::postScanMonitorAsyncResultEventFatal(
  348. uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
  349. const void *cookie) {
  350. if (!postScanMonitorAsyncResultEvent(nanoappInstanceId, success, enable,
  351. errorCode, cookie)) {
  352. FATAL_ERROR("Failed to send WiFi scan monitor async result event");
  353. }
  354. }
  355. bool WifiRequestManager::postScanRequestAsyncResultEvent(
  356. uint32_t nanoappInstanceId, bool success, uint8_t errorCode,
  357. const void *cookie) {
  358. bool eventPosted = false;
  359. chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
  360. if (event == nullptr) {
  361. LOG_OOM();
  362. } else {
  363. event->requestType = CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN;
  364. event->success = success;
  365. event->errorCode = errorCode;
  366. event->reserved = 0;
  367. event->cookie = cookie;
  368. // Post the event.
  369. eventPosted =
  370. EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
  371. CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
  372. nanoappInstanceId);
  373. }
  374. return eventPosted;
  375. }
  376. void WifiRequestManager::postScanRequestAsyncResultEventFatal(
  377. uint32_t nanoappInstanceId, bool success, uint8_t errorCode,
  378. const void *cookie) {
  379. if (!postScanRequestAsyncResultEvent(nanoappInstanceId, success, errorCode,
  380. cookie)) {
  381. FATAL_ERROR("Failed to send WiFi scan request async result event");
  382. }
  383. }
  384. void WifiRequestManager::postScanEventFatal(chreWifiScanEvent *event) {
  385. EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
  386. CHRE_EVENT_WIFI_SCAN_RESULT, event, freeWifiScanEventCallback);
  387. }
  388. void WifiRequestManager::handleScanMonitorStateChangeSync(bool enabled,
  389. uint8_t errorCode) {
  390. // Success is defined as having no errors ... in life ༼ つ ◕_◕ ༽つ
  391. bool success = (errorCode == CHRE_ERROR_NONE);
  392. // TODO(b/62904616): re-enable this assertion
  393. //CHRE_ASSERT_LOG(!mScanMonitorStateTransitions.empty(),
  394. // "handleScanMonitorStateChangeSync called with no transitions");
  395. if (mPendingScanMonitorRequests.empty()) {
  396. LOGE("WiFi PAL error: handleScanMonitorStateChangeSync called with no "
  397. "transitions (enabled %d errorCode %" PRIu8 ")", enabled, errorCode);
  398. }
  399. // Always check the front of the queue.
  400. if (!mPendingScanMonitorRequests.empty()) {
  401. const auto& stateTransition = mPendingScanMonitorRequests.front();
  402. success &= (stateTransition.enable == enabled);
  403. postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
  404. success, stateTransition.enable,
  405. errorCode, stateTransition.cookie);
  406. mPendingScanMonitorRequests.pop();
  407. }
  408. while (!mPendingScanMonitorRequests.empty()) {
  409. const auto& stateTransition = mPendingScanMonitorRequests.front();
  410. bool hasScanMonitorRequest = nanoappHasScanMonitorRequest(
  411. stateTransition.nanoappInstanceId);
  412. if (scanMonitorIsInRequestedState(
  413. stateTransition.enable, hasScanMonitorRequest)) {
  414. // We are already in the target state so just post an event indicating
  415. // success
  416. postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
  417. true /* success */,
  418. stateTransition.enable,
  419. CHRE_ERROR_NONE,
  420. stateTransition.cookie);
  421. } else if (scanMonitorStateTransitionIsRequired(
  422. stateTransition.enable, hasScanMonitorRequest)) {
  423. if (mPlatformWifi.configureScanMonitor(stateTransition.enable)) {
  424. break;
  425. } else {
  426. postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
  427. false /* success */,
  428. stateTransition.enable, CHRE_ERROR,
  429. stateTransition.cookie);
  430. }
  431. } else {
  432. CHRE_ASSERT_LOG(false, "Invalid scan monitor state");
  433. break;
  434. }
  435. mPendingScanMonitorRequests.pop();
  436. }
  437. }
  438. void WifiRequestManager::handleScanResponseSync(bool pending,
  439. uint8_t errorCode) {
  440. // TODO(b/65206783): re-enable this assertion
  441. //CHRE_ASSERT_LOG(mScanRequestingNanoappInstanceId.has_value(),
  442. // "handleScanResponseSync called with no outstanding request");
  443. if (!mScanRequestingNanoappInstanceId.has_value()) {
  444. LOGE("handleScanResponseSync called with no outstanding request");
  445. }
  446. // TODO: raise this to CHRE_ASSERT_LOG
  447. if (!pending && errorCode == CHRE_ERROR_NONE) {
  448. LOGE("Invalid wifi scan response");
  449. errorCode = CHRE_ERROR;
  450. }
  451. if (mScanRequestingNanoappInstanceId.has_value()) {
  452. bool success = (pending && errorCode == CHRE_ERROR_NONE);
  453. if (!success) {
  454. LOGW("Wifi scan request failed: pending %d, errorCode %" PRIu8,
  455. pending, errorCode);
  456. }
  457. postScanRequestAsyncResultEventFatal(*mScanRequestingNanoappInstanceId,
  458. success, errorCode,
  459. mScanRequestingNanoappCookie);
  460. // Set a flag to indicate that results may be pending.
  461. mScanRequestResultsArePending = pending;
  462. if (pending) {
  463. Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
  464. .findNanoappByInstanceId(*mScanRequestingNanoappInstanceId);
  465. if (nanoapp == nullptr) {
  466. LOGW("Received WiFi scan response for unknown nanoapp");
  467. } else {
  468. nanoapp->registerForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
  469. }
  470. } else {
  471. // If the scan results are not pending, clear the nanoapp instance ID.
  472. // Otherwise, wait for the results to be delivered and then clear the
  473. // instance ID.
  474. mScanRequestingNanoappInstanceId.reset();
  475. }
  476. }
  477. }
  478. bool WifiRequestManager::postRangingAsyncResult(uint8_t errorCode) {
  479. bool eventPosted = false;
  480. if (mPendingRangingRequests.empty()) {
  481. LOGE("Unexpected ranging event callback");
  482. } else {
  483. auto *event = memoryAlloc<struct chreAsyncResult>();
  484. if (event == nullptr) {
  485. LOG_OOM();
  486. } else {
  487. const PendingRangingRequest& req = mPendingRangingRequests.front();
  488. event->requestType = CHRE_WIFI_REQUEST_TYPE_RANGING;
  489. event->success = (errorCode == CHRE_ERROR_NONE);
  490. event->errorCode = errorCode;
  491. event->reserved = 0;
  492. event->cookie = req.cookie;
  493. eventPosted =
  494. EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
  495. CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
  496. req.nanoappInstanceId);
  497. if (!eventPosted) {
  498. memoryFree(event);
  499. }
  500. }
  501. }
  502. return eventPosted;
  503. }
  504. bool WifiRequestManager::dispatchQueuedRangingRequest() {
  505. const PendingRangingRequest& req = mPendingRangingRequests.front();
  506. struct chreWifiRangingParams params = {};
  507. params.targetListLen = static_cast<uint8_t>(req.targetList.size());
  508. params.targetList = req.targetList.data();
  509. bool success = mPlatformWifi.requestRanging(&params);
  510. if (!success) {
  511. LOGE("Failed to issue queued ranging result");
  512. postRangingAsyncResult(CHRE_ERROR);
  513. mPendingRangingRequests.pop();
  514. } else {
  515. mRangingResponseTimeout = SystemTime::getMonotonicTime()
  516. + Nanoseconds(CHRE_WIFI_RANGING_RESULT_TIMEOUT_NS);
  517. }
  518. return success;
  519. }
  520. void WifiRequestManager::handleRangingEventSync(
  521. uint8_t errorCode, struct chreWifiRangingEvent *event) {
  522. if (postRangingAsyncResult(errorCode)) {
  523. if (errorCode != CHRE_ERROR_NONE) {
  524. LOGW("RTT ranging failed with error %d", errorCode);
  525. } else {
  526. EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
  527. CHRE_EVENT_WIFI_RANGING_RESULT, event, freeWifiRangingEventCallback,
  528. mPendingRangingRequests.front().nanoappInstanceId);
  529. }
  530. mPendingRangingRequests.pop();
  531. }
  532. // If we have any pending requests, try issuing them to the platform until the
  533. // first one succeeds
  534. while (!mPendingRangingRequests.empty() && !dispatchQueuedRangingRequest());
  535. }
  536. void WifiRequestManager::handleFreeWifiScanEvent(chreWifiScanEvent *scanEvent) {
  537. if (mScanRequestResultsArePending) {
  538. // Reset the event distribution logic once an entire scan event has been
  539. // received and processed by the nanoapp requesting the scan event.
  540. mScanEventResultCountAccumulator += scanEvent->resultCount;
  541. if (mScanEventResultCountAccumulator >= scanEvent->resultTotal) {
  542. mScanEventResultCountAccumulator = 0;
  543. mScanRequestResultsArePending = false;
  544. }
  545. if (!mScanRequestResultsArePending
  546. && mScanRequestingNanoappInstanceId.has_value()) {
  547. Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
  548. .findNanoappByInstanceId(*mScanRequestingNanoappInstanceId);
  549. if (nanoapp == nullptr) {
  550. LOGW("Attempted to unsubscribe unknown nanoapp from WiFi scan events");
  551. } else if (!nanoappHasScanMonitorRequest(
  552. *mScanRequestingNanoappInstanceId)) {
  553. nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
  554. }
  555. mScanRequestingNanoappInstanceId.reset();
  556. }
  557. }
  558. mPlatformWifi.releaseScanEvent(scanEvent);
  559. }
  560. void WifiRequestManager::freeWifiScanEventCallback(uint16_t eventType,
  561. void *eventData) {
  562. chreWifiScanEvent *scanEvent = static_cast<chreWifiScanEvent *>(eventData);
  563. EventLoopManagerSingleton::get()->getWifiRequestManager()
  564. .handleFreeWifiScanEvent(scanEvent);
  565. }
  566. void WifiRequestManager::freeWifiRangingEventCallback(uint16_t eventType,
  567. void *eventData) {
  568. auto *event = static_cast<struct chreWifiRangingEvent *>(eventData);
  569. EventLoopManagerSingleton::get()->getWifiRequestManager()
  570. .mPlatformWifi.releaseRangingEvent(event);
  571. }
  572. } // namespace chre