wifi_request_manager.cc revision 84723e6849eb2d8e08557d57d787c5ab7ba01982
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();
4530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!mScanMonitorStateTransitions.empty()) {
4630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    success = addScanMonitorRequestToQueue(nanoapp, enable, cookie);
4730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  } else if (scanMonitorIsInRequestedState(enable, instanceId)) {
4830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    // The scan monitor is already in the requested state. A success event can
4930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    // be posted immediately.
5030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    success = postScanMonitorAsyncResultEvent(instanceId, true /* success */,
5130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                              enable, CHRE_ERROR_NONE, cookie);
5230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  } else if (scanMonitorStateTransitionIsRequired(enable, instanceId)) {
5330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    success = addScanMonitorRequestToQueue(nanoapp, enable, cookie);
5430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    if (success) {
5530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      success = mPlatformWifi.configureScanMonitor(enable);
5630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      if (!success) {
5730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        // TODO: Add a pop_back method.
5830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        mScanMonitorStateTransitions.remove(
5930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol            mScanMonitorStateTransitions.size() - 1);
6030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        LOGE("Failed to enable the scan monitor for nanoapp instance %" PRIu32,
6130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol             instanceId);
6230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      }
6330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
6430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  } else {
6530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    CHRE_ASSERT_LOG(false, "Invalid scan monitor configuration");
6630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
6730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
6830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return success;
6930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
7030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
7184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignolbool WifiRequestManager::requestScan(Nanoapp *nanoapp,
7284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                     const chreWifiScanParams *params,
7384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                     const void *cookie) {
7484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  CHRE_ASSERT(nanoapp);
7584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
7684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  bool success = false;
7784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  if (!mScanRequestingNanoappInstanceId.has_value()) {
7884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    success = mPlatformWifi.requestScan(params);
7984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    if (success) {
8084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      mScanRequestingNanoappInstanceId = nanoapp->getInstanceId();
8184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      mScanRequestingNanoappCookie = cookie;
8284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    }
8384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  } else {
8484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    LOGE("Active wifi scan request made while a request is in flight");
8584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
8684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
8784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  return success;
8884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol}
8984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
903a34ff2bf5e4afd466abb2b9af26abf719ec34fdAndrew Rossignolvoid WifiRequestManager::handleScanMonitorStateChange(bool enabled,
913a34ff2bf5e4afd466abb2b9af26abf719ec34fdAndrew Rossignol                                                      uint8_t errorCode) {
9230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  struct CallbackState {
9330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    bool enabled;
9430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    uint8_t errorCode;
9530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  };
9630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
9730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  auto *state = memoryAlloc<CallbackState>();
9830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (state == nullptr) {
9930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    LOGE("Failed to allocate callback state for scan monitor state change");
10030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  } else {
10130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    state->enabled = enabled;
10230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    state->errorCode = errorCode;
10330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
10430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    auto callback = [](uint16_t eventType, void *eventData) {
10530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      auto *state = static_cast<CallbackState *>(eventData);
10630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      EventLoopManagerSingleton::get()->getWifiRequestManager()
10730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol          .handleScanMonitorStateChangeSync(state->enabled, state->errorCode);
10830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      memoryFree(state);
10930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    };
11030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
11130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    EventLoopManagerSingleton::get()->deferCallback(
11230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        SystemCallbackType::WifiScanMonitorStateChange, state, callback);
11330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
114cbff0ad0e40b03ea9972e3446f1d238796e07398Andrew Rossignol}
115cbff0ad0e40b03ea9972e3446f1d238796e07398Andrew Rossignol
116d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignolvoid WifiRequestManager::handleScanResponse(bool pending,
117d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol                                            uint8_t errorCode) {
11884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  struct CallbackState {
11984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    bool pending;
12084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    uint8_t errorCode;
12184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  };
12284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
12384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  auto *state = memoryAlloc<CallbackState>();
12484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  if (state == nullptr) {
12584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    LOGE("Failed to allocate callback state for wifi scan response");
12684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  } else {
12784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    state->pending = pending;
12884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    state->errorCode = errorCode;
12984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
13084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    auto callback = [](uint16_t eventType, void *eventData) {
13184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      auto *state = static_cast<CallbackState *>(eventData);
13284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      EventLoopManagerSingleton::get()->getWifiRequestManager()
13384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol          .handleScanResponseSync(state->pending, state->errorCode);
13484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      memoryFree(state);
13584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    };
13684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
13784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    EventLoopManagerSingleton::get()->deferCallback(
13884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol        SystemCallbackType::WifiRequestScanResponse, state, callback);
13984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
140d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol}
141d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol
142d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignolvoid WifiRequestManager::handleScanEvent(chreWifiScanEvent *event) {
143d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol  // TODO: Implement this.
144d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol}
145d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol
14630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::scanMonitorIsEnabled() const {
14730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return !mScanMonitorNanoapps.empty();
14830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
14930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
15030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::nanoappHasScanMonitorRequest(
15130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    uint32_t instanceId, size_t *nanoappIndex) const {
15230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  size_t index = mScanMonitorNanoapps.find(instanceId);
15330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool hasScanMonitorRequest = (index == mScanMonitorNanoapps.size());
15430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (hasScanMonitorRequest && nanoappIndex != nullptr) {
15530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    *nanoappIndex = index;
15630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
15730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
15830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return hasScanMonitorRequest;
15930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
16030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
16130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::scanMonitorIsInRequestedState(
16230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    bool requestedState, bool nanoappHasRequest) const {
16330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return (requestedState == scanMonitorIsEnabled() || (!requestedState
16430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      && (!nanoappHasRequest || mScanMonitorNanoapps.size() > 1)));
16530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
16630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
16730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::scanMonitorStateTransitionIsRequired(
16830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    bool requestedState, bool nanoappHasRequest) const {
16930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return ((requestedState && mScanMonitorNanoapps.empty())
17030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      || (!requestedState && nanoappHasRequest
17130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol              && mScanMonitorNanoapps.size() == 1));
17230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
17330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
17430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::addScanMonitorRequestToQueue(Nanoapp *nanoapp,
17530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                      bool enable,
17630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                      const void *cookie) {
17730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  ScanMonitorStateTransition scanMonitorStateTransition;
17830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  scanMonitorStateTransition.nanoappInstanceId = nanoapp->getInstanceId();
17930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  scanMonitorStateTransition.cookie = cookie;
18030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  scanMonitorStateTransition.enable = enable;
18130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
18230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool success = mScanMonitorStateTransitions.push(scanMonitorStateTransition);
18330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!success) {
18430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    LOGW("Too many scan monitor state transitions");
18530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
18630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
18730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return success;
18830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
18930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
19030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::updateNanoappScanMonitoringList(bool enable,
19130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                         uint32_t instanceId) {
19230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool success = true;
19330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  size_t nanoappIndex;
19430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool hasExistingRequest = nanoappHasScanMonitorRequest(instanceId,
19530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                         &nanoappIndex);
19630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (enable) {
19730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    if (!hasExistingRequest) {
19830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // The scan monitor was successfully enabled for this nanoapp and there
19930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // is no existing request. Add it to the list of scan monitoring
20030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // nanoapps.
20130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      success = mScanMonitorNanoapps.push_back(instanceId);
20230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      if (!success) {
20330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        LOGE("Failed to add nanoapp to the list of scan monitoring nanoapps");
20430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      }
20530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
20630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  } else {
20730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    if (!hasExistingRequest) {
20830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      success = false;
20930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      LOGE("Received a scan monitor state change for a non-existent nanoapp");
21030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    } else {
21130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // The scan monitor was successfully disabled for a previously enabled
21230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // nanoapp. Remove it from the list of scan monitoring nanoapps.
21330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      mScanMonitorNanoapps.erase(nanoappIndex);
21430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
21530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
21630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
21730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return success;
21830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
21930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
22030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::postScanMonitorAsyncResultEvent(
22130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
22230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    const void *cookie) {
22330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // Allocate and post an event to the nanoapp requesting wifi.
22430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool eventPosted = false;
22530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!success || updateNanoappScanMonitoringList(enable, nanoappInstanceId)) {
22630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
22730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    if (event == nullptr) {
22830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      LOGE("Failed to allocate wifi scan monitor async result event");
22930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    } else {
23030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->requestType = CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR;
23130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->success = success;
23230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->errorCode = errorCode;
23330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->reserved = 0;
23430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->cookie = cookie;
23530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
23630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // Post the event.
23730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      eventPosted = EventLoopManagerSingleton::get()->postEvent(
23830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol          CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeWifiAsyncResultCallback,
23930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol          kSystemInstanceId, nanoappInstanceId);
24030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
24130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
24230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
24330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return eventPosted;
24430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
24530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
24630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolvoid WifiRequestManager::postScanMonitorAsyncResultEventFatal(
24730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
24830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    const void *cookie) {
24930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!postScanMonitorAsyncResultEvent(nanoappInstanceId, success, enable,
25030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                       errorCode, cookie)) {
25130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    FATAL_ERROR("Failed to send WiFi scan monitor async result event");
25230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
25330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
25430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
25584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignolbool WifiRequestManager::postScanRequestAsyncResultEvent(
25684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    uint32_t nanoappInstanceId, bool success, uint8_t errorCode,
25784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    const void *cookie) {
25884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  bool eventPosted = false;
25984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
26084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  if (event == nullptr) {
26184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    LOGE("Failed to allocate wifi scan request async result event");
26284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  } else {
26384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->requestType = CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN;
26484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->success = success;
26584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->errorCode = errorCode;
26684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->reserved = 0;
26784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->cookie = cookie;
26884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
26984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    // Post the event.
27084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    eventPosted = EventLoopManagerSingleton::get()->postEvent(
27184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol        CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeWifiAsyncResultCallback,
27284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol        kSystemInstanceId, nanoappInstanceId);
27384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
27484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
27584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  return eventPosted;
27684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol}
27784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
27884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignolvoid WifiRequestManager::postScanRequestAsyncResultEventFatal(
27984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    uint32_t nanoappInstanceId, bool success, uint8_t errorCode,
28084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    const void *cookie) {
28184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  if (!postScanRequestAsyncResultEvent(nanoappInstanceId, success, errorCode,
28284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                       cookie)) {
28384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    FATAL_ERROR("Failed to send WiFi scan request async result event");
28484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
28584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol}
28684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
28730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolvoid WifiRequestManager::handleScanMonitorStateChangeSync(bool enabled,
28830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                          uint8_t errorCode) {
28930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // Success is defined as having no errors ... in life ༼ つ ◕_◕ ༽つ
29030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool success = (errorCode == CHRE_ERROR_NONE);
29130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
29230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // Always check the front of the queue.
29330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  CHRE_ASSERT_LOG(!mScanMonitorStateTransitions.empty(),
29484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                  "handleScanMonitorStateChangeSync called with no transitions");
29530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!mScanMonitorStateTransitions.empty()) {
29630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    const auto& stateTransition = mScanMonitorStateTransitions.front();
29730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    success &= (stateTransition.enable == enabled);
29830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
29930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                         success, stateTransition.enable,
30030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                         errorCode, stateTransition.cookie);
30130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    mScanMonitorStateTransitions.pop();
30230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
30330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
30430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  while (!mScanMonitorStateTransitions.empty()) {
30530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    const auto& stateTransition = mScanMonitorStateTransitions.front();
30630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    bool hasScanMonitorRequest = nanoappHasScanMonitorRequest(
30730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        stateTransition.nanoappInstanceId);
30830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    if (scanMonitorIsInRequestedState(
30930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        stateTransition.enable, hasScanMonitorRequest)) {
31030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // We are already in the target state so just post an event indicating
31130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // success
31230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
31330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                           success, stateTransition.enable,
31430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                           errorCode, stateTransition.cookie);
31530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    } else if (scanMonitorStateTransitionIsRequired(
31630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        stateTransition.enable, hasScanMonitorRequest)) {
31730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      if (mPlatformWifi.configureScanMonitor(stateTransition.enable)) {
31830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        break;
31930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      } else {
32030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
32130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                             false /* success */,
32230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                             stateTransition.enable, CHRE_ERROR,
32330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                             stateTransition.cookie);
32430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      }
32530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    } else {
32630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      CHRE_ASSERT_LOG(false, "Invalid scan monitor state");
32730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      break;
32830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
32930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
33030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    mScanMonitorStateTransitions.pop();
33130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
33230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
33330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
33484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignolvoid WifiRequestManager::handleScanResponseSync(bool pending,
33584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                                uint8_t errorCode) {
33684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  CHRE_ASSERT_LOG(mScanRequestingNanoappInstanceId.has_value(),
33784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                  "handleScanResponseSync called with no outstanding request");
33884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  if (mScanRequestingNanoappInstanceId.has_value()) {
33984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    bool success = (pending && errorCode == CHRE_ERROR_NONE);
34084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    postScanRequestAsyncResultEventFatal(*mScanRequestingNanoappInstanceId,
34184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                         success, errorCode,
34284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                         mScanRequestingNanoappCookie);
34384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    if (!pending) {
34484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      // If the scan results are not pending, clear the nanoapp instance ID.
34584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      // Otherwise, wait for the results to be delivered and then clear the
34684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      // instance ID.
34784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      mScanRequestingNanoappInstanceId.reset();
34884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    }
34984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
35084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol}
35184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
35230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolvoid WifiRequestManager::freeWifiAsyncResultCallback(uint16_t eventType,
35330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                     void *eventData) {
35430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  memoryFree(eventData);
35530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
35630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
35756b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol}  // namespace chre
358