wifi_request_manager.cc revision 1c815825047c0a8974f4d59fd6120766eca672d0
156b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol/*
256b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol * Copyright (C) 2016 The Android Open Source Project
356b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol *
456b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol * Licensed under the Apache License, Version 2.0 (the "License");
556b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol * you may not use this file except in compliance with the License.
656b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol * You may obtain a copy of the License at
756b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol *
856b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol *      http://www.apache.org/licenses/LICENSE-2.0
956b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol *
1056b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol * Unless required by applicable law or agreed to in writing, software
1156b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol * distributed under the License is distributed on an "AS IS" BASIS,
1256b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1356b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol * See the License for the specific language governing permissions and
1456b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol * limitations under the License.
1556b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol */
1656b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol
1756b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol#include <cinttypes>
1856b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol
1930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol#include "chre/core/event_loop_manager.h"
2056b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol#include "chre/core/wifi_request_manager.h"
2130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol#include "chre/platform/fatal_error.h"
2256b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol#include "chre/platform/log.h"
2356b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol
2456b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignolnamespace chre {
2556b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol
2630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew RossignolWifiRequestManager::WifiRequestManager() {
2730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // Reserve space for at least one scan monitoring nanoapp. This ensures that
2830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // the first asynchronous push_back will succeed. Future push_backs will be
2930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // synchronous and failures will be returned to the client.
3030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!mScanMonitorNanoapps.reserve(1)) {
3130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    FATAL_ERROR("Failed to allocate scan monitoring nanoapps list at startup");
3230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
3330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
3430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
35bdf404267034f69fc1555ef266d9dd12ba9215eeAndrew Rossignoluint32_t WifiRequestManager::getCapabilities() {
36bdf404267034f69fc1555ef266d9dd12ba9215eeAndrew Rossignol  return mPlatformWifi.getCapabilities();
3756b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol}
3856b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol
3930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::configureScanMonitor(Nanoapp *nanoapp, bool enable,
4030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                              const void *cookie) {
4130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  CHRE_ASSERT(nanoapp);
4230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
4330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool success = false;
4430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  uint32_t instanceId = nanoapp->getInstanceId();
45dfabf1a03bcf4184074fb2c397c17022c41acdbaAndrew Rossignol  bool hasScanMonitorRequest = nanoappHasScanMonitorRequest(instanceId);
4630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!mScanMonitorStateTransitions.empty()) {
4730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    success = addScanMonitorRequestToQueue(nanoapp, enable, cookie);
48dfabf1a03bcf4184074fb2c397c17022c41acdbaAndrew Rossignol  } else if (scanMonitorIsInRequestedState(enable, hasScanMonitorRequest)) {
4930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    // The scan monitor is already in the requested state. A success event can
5030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    // be posted immediately.
5130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    success = postScanMonitorAsyncResultEvent(instanceId, true /* success */,
5230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                              enable, CHRE_ERROR_NONE, cookie);
53dfabf1a03bcf4184074fb2c397c17022c41acdbaAndrew Rossignol  } else if (scanMonitorStateTransitionIsRequired(enable,
54dfabf1a03bcf4184074fb2c397c17022c41acdbaAndrew Rossignol                                                  hasScanMonitorRequest)) {
5530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    success = addScanMonitorRequestToQueue(nanoapp, enable, cookie);
5630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    if (success) {
5730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      success = mPlatformWifi.configureScanMonitor(enable);
5830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      if (!success) {
5930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        // TODO: Add a pop_back method.
6030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        mScanMonitorStateTransitions.remove(
6130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol            mScanMonitorStateTransitions.size() - 1);
6230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        LOGE("Failed to enable the scan monitor for nanoapp instance %" PRIu32,
6330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol             instanceId);
6430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      }
6530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
6630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  } else {
6730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    CHRE_ASSERT_LOG(false, "Invalid scan monitor configuration");
6830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
6930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
7030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return success;
7130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
7230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
7384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignolbool WifiRequestManager::requestScan(Nanoapp *nanoapp,
7484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                     const chreWifiScanParams *params,
7584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                     const void *cookie) {
7684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  CHRE_ASSERT(nanoapp);
7784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
7884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  bool success = false;
7984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  if (!mScanRequestingNanoappInstanceId.has_value()) {
8084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    success = mPlatformWifi.requestScan(params);
8184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    if (success) {
8284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      mScanRequestingNanoappInstanceId = nanoapp->getInstanceId();
8384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      mScanRequestingNanoappCookie = cookie;
8484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    }
8584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  } else {
8684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    LOGE("Active wifi scan request made while a request is in flight");
8784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
8884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
8984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  return success;
9084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol}
9184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
923a34ff2bf5e4afd466abb2b9af26abf719ec34fdAndrew Rossignolvoid WifiRequestManager::handleScanMonitorStateChange(bool enabled,
933a34ff2bf5e4afd466abb2b9af26abf719ec34fdAndrew Rossignol                                                      uint8_t errorCode) {
9430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  struct CallbackState {
9530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    bool enabled;
9630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    uint8_t errorCode;
9730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  };
9830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
99a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie  auto *cbState = memoryAlloc<CallbackState>();
100a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie  if (cbState == nullptr) {
10130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    LOGE("Failed to allocate callback state for scan monitor state change");
10230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  } else {
103a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie    cbState->enabled = enabled;
104a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie    cbState->errorCode = errorCode;
10530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
10696f33751ce98a3e64d90373a3a42f88458b3aef0Andrew Rossignol    auto callback = [](uint16_t /* eventType */, void *eventData) {
10730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      auto *state = static_cast<CallbackState *>(eventData);
10830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      EventLoopManagerSingleton::get()->getWifiRequestManager()
10930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol          .handleScanMonitorStateChangeSync(state->enabled, state->errorCode);
11030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      memoryFree(state);
11130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    };
11230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
11319b9a23f49844d0334780be8eaf339d6065d2a36Andrew Rossignol    bool callbackDeferred = EventLoopManagerSingleton::get()->deferCallback(
114a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie        SystemCallbackType::WifiScanMonitorStateChange, cbState, callback);
11519b9a23f49844d0334780be8eaf339d6065d2a36Andrew Rossignol    if (!callbackDeferred) {
11619b9a23f49844d0334780be8eaf339d6065d2a36Andrew Rossignol      memoryFree(cbState);
11719b9a23f49844d0334780be8eaf339d6065d2a36Andrew Rossignol    }
11830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
119cbff0ad0e40b03ea9972e3446f1d238796e07398Andrew Rossignol}
120cbff0ad0e40b03ea9972e3446f1d238796e07398Andrew Rossignol
121d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignolvoid WifiRequestManager::handleScanResponse(bool pending,
122d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol                                            uint8_t errorCode) {
12384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  struct CallbackState {
12484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    bool pending;
12584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    uint8_t errorCode;
12684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  };
12784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
128a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie  auto *cbState = memoryAlloc<CallbackState>();
129a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie  if (cbState == nullptr) {
13084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    LOGE("Failed to allocate callback state for wifi scan response");
13184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  } else {
132a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie    cbState->pending = pending;
133a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie    cbState->errorCode = errorCode;
13484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
13596f33751ce98a3e64d90373a3a42f88458b3aef0Andrew Rossignol    auto callback = [](uint16_t /* eventType */, void *eventData) {
13684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      auto *state = static_cast<CallbackState *>(eventData);
13784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      EventLoopManagerSingleton::get()->getWifiRequestManager()
13884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol          .handleScanResponseSync(state->pending, state->errorCode);
13984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      memoryFree(state);
14084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    };
14184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
14284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    EventLoopManagerSingleton::get()->deferCallback(
143a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie        SystemCallbackType::WifiRequestScanResponse, cbState, callback);
14484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
145d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol}
146d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol
147d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignolvoid WifiRequestManager::handleScanEvent(chreWifiScanEvent *event) {
148254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  auto callback = [](uint16_t eventType, void *eventData) {
149254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    chreWifiScanEvent *scanEvent = static_cast<chreWifiScanEvent *>(eventData);
150254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    EventLoopManagerSingleton::get()->getWifiRequestManager()
151254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        .handleScanEventSync(scanEvent);
152254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  };
153254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
154254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  EventLoopManagerSingleton::get()->deferCallback(
155254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      SystemCallbackType::WifiHandleScanEvent, event, callback);
156d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol}
157d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol
15830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::scanMonitorIsEnabled() const {
15930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return !mScanMonitorNanoapps.empty();
16030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
16130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
16230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::nanoappHasScanMonitorRequest(
16330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    uint32_t instanceId, size_t *nanoappIndex) const {
16430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  size_t index = mScanMonitorNanoapps.find(instanceId);
16544b56ef8ab3ef4de08f2fc84e469dfb3e84e8d08Andrew Rossignol  bool hasScanMonitorRequest = (index != mScanMonitorNanoapps.size());
16630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (hasScanMonitorRequest && nanoappIndex != nullptr) {
16730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    *nanoappIndex = index;
16830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
16930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
17030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return hasScanMonitorRequest;
17130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
17230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
17330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::scanMonitorIsInRequestedState(
17430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    bool requestedState, bool nanoappHasRequest) const {
17530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return (requestedState == scanMonitorIsEnabled() || (!requestedState
17630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      && (!nanoappHasRequest || mScanMonitorNanoapps.size() > 1)));
17730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
17830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
17930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::scanMonitorStateTransitionIsRequired(
18030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    bool requestedState, bool nanoappHasRequest) const {
18130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return ((requestedState && mScanMonitorNanoapps.empty())
18230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      || (!requestedState && nanoappHasRequest
18330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol              && mScanMonitorNanoapps.size() == 1));
18430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
18530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
18630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::addScanMonitorRequestToQueue(Nanoapp *nanoapp,
18730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                      bool enable,
18830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                      const void *cookie) {
18930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  ScanMonitorStateTransition scanMonitorStateTransition;
19030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  scanMonitorStateTransition.nanoappInstanceId = nanoapp->getInstanceId();
19130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  scanMonitorStateTransition.cookie = cookie;
19230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  scanMonitorStateTransition.enable = enable;
19330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
19430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool success = mScanMonitorStateTransitions.push(scanMonitorStateTransition);
19530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!success) {
19630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    LOGW("Too many scan monitor state transitions");
19730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
19830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
19930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return success;
20030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
20130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
20230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::updateNanoappScanMonitoringList(bool enable,
20330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                         uint32_t instanceId) {
20430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool success = true;
20550d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol  Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
20650d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol      .findNanoappByInstanceId(instanceId);
207254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  if (nanoapp == nullptr) {
208254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    CHRE_ASSERT_LOG(false, "Failed to update scan monitoring list for "
209254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol                    "non-existent nanoapp");
21030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  } else {
211254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    size_t nanoappIndex;
212254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    bool hasExistingRequest = nanoappHasScanMonitorRequest(instanceId,
213254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol                                                           &nanoappIndex);
214254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    if (enable) {
215254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      if (!hasExistingRequest) {
216254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        success = nanoapp->registerForBroadcastEvent(
217254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol            CHRE_EVENT_WIFI_SCAN_RESULT);
218254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        if (!success) {
219254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          LOGE("Failed to register nanoapp for wifi scan events");
220254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        } else {
221254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          // The scan monitor was successfully enabled for this nanoapp and
222254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          // there is no existing request. Add it to the list of scan monitoring
223254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          // nanoapps.
224254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          success = mScanMonitorNanoapps.push_back(instanceId);
225254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          if (!success) {
226254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol            nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
227254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol            LOGE("Failed to add nanoapp to the list of scan monitoring "
228254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol                 "nanoapps");
229254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          }
230254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        }
231254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      }
23230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    } else {
233254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      if (!hasExistingRequest) {
234254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        success = false;
235254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        LOGE("Received a scan monitor state change for a non-existent nanoapp");
236254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      } else {
237254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        // The scan monitor was successfully disabled for a previously enabled
238254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        // nanoapp. Remove it from the list of scan monitoring nanoapps.
239254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        mScanMonitorNanoapps.erase(nanoappIndex);
240254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
241254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      }
24230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
24330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
24430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
24530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return success;
24630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
24730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
24830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::postScanMonitorAsyncResultEvent(
24930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
25030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    const void *cookie) {
25130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // Allocate and post an event to the nanoapp requesting wifi.
25230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool eventPosted = false;
25330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!success || updateNanoappScanMonitoringList(enable, nanoappInstanceId)) {
25430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
25530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    if (event == nullptr) {
25630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      LOGE("Failed to allocate wifi scan monitor async result event");
25730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    } else {
25830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->requestType = CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR;
25930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->success = success;
26030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->errorCode = errorCode;
26130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->reserved = 0;
26230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->cookie = cookie;
26330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
26430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // Post the event.
26550d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol      eventPosted = EventLoopManagerSingleton::get()->getEventLoop()
26650d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol          .postEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
26750d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol                     kSystemInstanceId, nanoappInstanceId);
2687e2da194710e593ad1248d4fc78b57d71ad01faaAndrew Rossignol      if (!eventPosted) {
2697e2da194710e593ad1248d4fc78b57d71ad01faaAndrew Rossignol        memoryFree(event);
2707e2da194710e593ad1248d4fc78b57d71ad01faaAndrew Rossignol      }
27130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
27230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
27330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
27430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return eventPosted;
27530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
27630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
27730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolvoid WifiRequestManager::postScanMonitorAsyncResultEventFatal(
27830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
27930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    const void *cookie) {
28030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!postScanMonitorAsyncResultEvent(nanoappInstanceId, success, enable,
28130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                       errorCode, cookie)) {
28230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    FATAL_ERROR("Failed to send WiFi scan monitor async result event");
28330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
28430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
28530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
28684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignolbool WifiRequestManager::postScanRequestAsyncResultEvent(
28784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    uint32_t nanoappInstanceId, bool success, uint8_t errorCode,
28884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    const void *cookie) {
28984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  bool eventPosted = false;
29084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
29184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  if (event == nullptr) {
29284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    LOGE("Failed to allocate wifi scan request async result event");
29384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  } else {
29484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->requestType = CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN;
29584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->success = success;
29684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->errorCode = errorCode;
29784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->reserved = 0;
29884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->cookie = cookie;
29984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
30084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    // Post the event.
30150d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol    eventPosted = EventLoopManagerSingleton::get()->getEventLoop()
30250d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol        .postEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
30350d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol                   kSystemInstanceId, nanoappInstanceId);
30484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
30584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
30684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  return eventPosted;
30784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol}
30884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
30984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignolvoid WifiRequestManager::postScanRequestAsyncResultEventFatal(
31084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    uint32_t nanoappInstanceId, bool success, uint8_t errorCode,
31184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    const void *cookie) {
31284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  if (!postScanRequestAsyncResultEvent(nanoappInstanceId, success, errorCode,
31384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                       cookie)) {
31484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    FATAL_ERROR("Failed to send WiFi scan request async result event");
31584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
31684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol}
31784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
318254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignolvoid WifiRequestManager::postScanEventFatal(chreWifiScanEvent *event) {
31950d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol  bool eventPosted = EventLoopManagerSingleton::get()->getEventLoop()
32050d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol      .postEvent(CHRE_EVENT_WIFI_SCAN_RESULT, event, freeWifiScanEventCallback,
32150d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol                 kSystemInstanceId, kBroadcastInstanceId);
322254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  if (!eventPosted) {
323254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    FATAL_ERROR("Failed to send WiFi scan event");
324254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  }
325254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol}
326254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
32730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolvoid WifiRequestManager::handleScanMonitorStateChangeSync(bool enabled,
32830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                          uint8_t errorCode) {
32930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // Success is defined as having no errors ... in life ༼ つ ◕_◕ ༽つ
33030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool success = (errorCode == CHRE_ERROR_NONE);
33130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
3321c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie  // TODO(b/62904616): re-enable this assertion
3331c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie  //CHRE_ASSERT_LOG(!mScanMonitorStateTransitions.empty(),
3341c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie  //                "handleScanMonitorStateChangeSync called with no transitions");
3351c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie  if (mScanMonitorStateTransitions.empty()) {
3361c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie    LOGE("WiFi PAL error: handleScanMonitorStateChangeSync called with no "
3371c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie         "transitions (enabled %d errorCode %" PRIu8 ")", enabled, errorCode);
3381c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie  }
3391c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie
34030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // Always check the front of the queue.
34130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!mScanMonitorStateTransitions.empty()) {
34230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    const auto& stateTransition = mScanMonitorStateTransitions.front();
34330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    success &= (stateTransition.enable == enabled);
34430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
34530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                         success, stateTransition.enable,
34630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                         errorCode, stateTransition.cookie);
34730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    mScanMonitorStateTransitions.pop();
34830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
34930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
35030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  while (!mScanMonitorStateTransitions.empty()) {
35130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    const auto& stateTransition = mScanMonitorStateTransitions.front();
35230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    bool hasScanMonitorRequest = nanoappHasScanMonitorRequest(
35330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        stateTransition.nanoappInstanceId);
35430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    if (scanMonitorIsInRequestedState(
35530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        stateTransition.enable, hasScanMonitorRequest)) {
35630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // We are already in the target state so just post an event indicating
35730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // success
35830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
35930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                           success, stateTransition.enable,
36030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                           errorCode, stateTransition.cookie);
36130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    } else if (scanMonitorStateTransitionIsRequired(
36230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        stateTransition.enable, hasScanMonitorRequest)) {
36330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      if (mPlatformWifi.configureScanMonitor(stateTransition.enable)) {
36430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        break;
36530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      } else {
36630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
36730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                             false /* success */,
36830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                             stateTransition.enable, CHRE_ERROR,
36930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                             stateTransition.cookie);
37030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      }
37130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    } else {
37230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      CHRE_ASSERT_LOG(false, "Invalid scan monitor state");
37330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      break;
37430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
37530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
37630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    mScanMonitorStateTransitions.pop();
37730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
37830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
37930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
38084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignolvoid WifiRequestManager::handleScanResponseSync(bool pending,
38184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                                uint8_t errorCode) {
38284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  CHRE_ASSERT_LOG(mScanRequestingNanoappInstanceId.has_value(),
38384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                  "handleScanResponseSync called with no outstanding request");
38484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  if (mScanRequestingNanoappInstanceId.has_value()) {
38584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    bool success = (pending && errorCode == CHRE_ERROR_NONE);
38684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    postScanRequestAsyncResultEventFatal(*mScanRequestingNanoappInstanceId,
38784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                         success, errorCode,
38884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                         mScanRequestingNanoappCookie);
389254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
390254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    // Set a flag to indicate that results may be pending.
391254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    mScanRequestResultsArePending = pending;
392254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
393254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    if (pending) {
39450d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol      Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
39550d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol          .findNanoappByInstanceId(*mScanRequestingNanoappInstanceId);
396254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      if (nanoapp == nullptr) {
397254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        CHRE_ASSERT_LOG(false, "Received WiFi scan response for unknown "
398254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol                        "nanoapp");
399254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      } else {
400254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        nanoapp->registerForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
401254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      }
402254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    } else {
40384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      // If the scan results are not pending, clear the nanoapp instance ID.
40484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      // Otherwise, wait for the results to be delivered and then clear the
40584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      // instance ID.
40684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      mScanRequestingNanoappInstanceId.reset();
40784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    }
40884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
40984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol}
41084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
411254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignolvoid WifiRequestManager::handleScanEventSync(chreWifiScanEvent *event) {
412254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  if (mScanRequestResultsArePending) {
413254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    // Reset the event distribution logic once an entire scan event has been
414254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    // received.
415254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    mScanEventResultCountAccumulator += event->resultCount;
416254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    if (mScanEventResultCountAccumulator >= event->resultTotal) {
417254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      mScanEventResultCountAccumulator = 0;
418254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      mScanRequestResultsArePending = false;
419254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    }
420254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  }
421254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
422254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  postScanEventFatal(event);
423254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol}
424254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
425254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignolvoid WifiRequestManager::handleFreeWifiScanEvent(chreWifiScanEvent *scanEvent) {
426254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  mPlatformWifi.releaseScanEvent(scanEvent);
427254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
428254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  if (!mScanRequestResultsArePending
429254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      && mScanRequestingNanoappInstanceId.has_value()) {
43050d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol    Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
43150d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol        .findNanoappByInstanceId(*mScanRequestingNanoappInstanceId);
432254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    if (nanoapp == nullptr) {
433254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      CHRE_ASSERT_LOG(false, "Attempted to unsubscribe unknown nanoapp from "
434254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol                      "WiFi scan events");
435254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    } else if (!nanoappHasScanMonitorRequest(*mScanRequestingNanoappInstanceId)) {
436254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
437254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    }
438254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
439254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    mScanRequestingNanoappInstanceId.reset();
440254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  }
441254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol}
442254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
443254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignolvoid WifiRequestManager::freeWifiScanEventCallback(uint16_t eventType,
444254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol                                                   void *eventData) {
445254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  chreWifiScanEvent *scanEvent = static_cast<chreWifiScanEvent *>(eventData);
446254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  EventLoopManagerSingleton::get()->getWifiRequestManager()
447254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      .handleFreeWifiScanEvent(scanEvent);
448254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol}
449254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
45056b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol}  // namespace chre
451