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"
233aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung#include "chre/platform/system_time.h"
247e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro#include "chre/util/system/debug_dump.h"
2556b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol
2656b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignolnamespace chre {
2756b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol
2830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew RossignolWifiRequestManager::WifiRequestManager() {
2930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // Reserve space for at least one scan monitoring nanoapp. This ensures that
3030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // the first asynchronous push_back will succeed. Future push_backs will be
3130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // synchronous and failures will be returned to the client.
3230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!mScanMonitorNanoapps.reserve(1)) {
3330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    FATAL_ERROR("Failed to allocate scan monitoring nanoapps list at startup");
3430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
3530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
3630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
372ff52c6627054f8708e83eaccbcbd0db0af2899cBrian Duddievoid WifiRequestManager::init() {
382ff52c6627054f8708e83eaccbcbd0db0af2899cBrian Duddie  mPlatformWifi.init();
392ff52c6627054f8708e83eaccbcbd0db0af2899cBrian Duddie}
402ff52c6627054f8708e83eaccbcbd0db0af2899cBrian Duddie
41bdf404267034f69fc1555ef266d9dd12ba9215eeAndrew Rossignoluint32_t WifiRequestManager::getCapabilities() {
42bdf404267034f69fc1555ef266d9dd12ba9215eeAndrew Rossignol  return mPlatformWifi.getCapabilities();
4356b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol}
4456b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol
4530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::configureScanMonitor(Nanoapp *nanoapp, bool enable,
4630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                              const void *cookie) {
4730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  CHRE_ASSERT(nanoapp);
4830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
4930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool success = false;
5030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  uint32_t instanceId = nanoapp->getInstanceId();
51dfabf1a03bcf4184074fb2c397c17022c41acdbaAndrew Rossignol  bool hasScanMonitorRequest = nanoappHasScanMonitorRequest(instanceId);
5230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!mScanMonitorStateTransitions.empty()) {
5330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    success = addScanMonitorRequestToQueue(nanoapp, enable, cookie);
54dfabf1a03bcf4184074fb2c397c17022c41acdbaAndrew Rossignol  } else if (scanMonitorIsInRequestedState(enable, hasScanMonitorRequest)) {
5530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    // The scan monitor is already in the requested state. A success event can
5630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    // be posted immediately.
5730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    success = postScanMonitorAsyncResultEvent(instanceId, true /* success */,
5830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                              enable, CHRE_ERROR_NONE, cookie);
59dfabf1a03bcf4184074fb2c397c17022c41acdbaAndrew Rossignol  } else if (scanMonitorStateTransitionIsRequired(enable,
60dfabf1a03bcf4184074fb2c397c17022c41acdbaAndrew Rossignol                                                  hasScanMonitorRequest)) {
6130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    success = addScanMonitorRequestToQueue(nanoapp, enable, cookie);
6230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    if (success) {
6330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      success = mPlatformWifi.configureScanMonitor(enable);
6430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      if (!success) {
6530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        // TODO: Add a pop_back method.
6630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        mScanMonitorStateTransitions.remove(
6730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol            mScanMonitorStateTransitions.size() - 1);
6830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        LOGE("Failed to enable the scan monitor for nanoapp instance %" PRIu32,
6930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol             instanceId);
7030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      }
7130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
7230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  } else {
7330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    CHRE_ASSERT_LOG(false, "Invalid scan monitor configuration");
7430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
7530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
7630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return success;
7730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
7830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
7984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignolbool WifiRequestManager::requestScan(Nanoapp *nanoapp,
8084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                     const chreWifiScanParams *params,
8184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                     const void *cookie) {
8284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  CHRE_ASSERT(nanoapp);
8384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
843aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung  // TODO(b/65331248): replace with a timer to actively check response timeout
853aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung  bool timedOut = (mScanRequestingNanoappInstanceId.has_value()
863aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung                   && mLastScanRequestTime
873aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung                       + Nanoseconds(CHRE_WIFI_SCAN_RESULT_TIMEOUT_NS)
883aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung                     < SystemTime::getMonotonicTime());
893aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung  if (timedOut) {
903aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung    LOGE("Scan request async response timed out");
913aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung    mScanRequestingNanoappInstanceId.reset();
923aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung  }
933aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung
9484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  bool success = false;
953aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung  if (mScanRequestingNanoappInstanceId.has_value()) {
963aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung     LOGE("Active wifi scan request made while a request is in flight");
973aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung  } else {
9884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    success = mPlatformWifi.requestScan(params);
993aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung    if (!success) {
1003aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung      LOGE("Wifi scan request failed");
1013aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung    } else {
10284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      mScanRequestingNanoappInstanceId = nanoapp->getInstanceId();
10384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      mScanRequestingNanoappCookie = cookie;
1043aacb4a3c98be3ef998911064c3e7e49047cb944Meng-hsuan Chung      mLastScanRequestTime = SystemTime::getMonotonicTime();
10584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    }
10684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
10784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
10884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  return success;
10984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol}
11084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
1113a34ff2bf5e4afd466abb2b9af26abf719ec34fdAndrew Rossignolvoid WifiRequestManager::handleScanMonitorStateChange(bool enabled,
1123a34ff2bf5e4afd466abb2b9af26abf719ec34fdAndrew Rossignol                                                      uint8_t errorCode) {
11330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  struct CallbackState {
11430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    bool enabled;
11530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    uint8_t errorCode;
11630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  };
11730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
118a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie  auto *cbState = memoryAlloc<CallbackState>();
119a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie  if (cbState == nullptr) {
12030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    LOGE("Failed to allocate callback state for scan monitor state change");
12130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  } else {
122a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie    cbState->enabled = enabled;
123a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie    cbState->errorCode = errorCode;
12430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
12596f33751ce98a3e64d90373a3a42f88458b3aef0Andrew Rossignol    auto callback = [](uint16_t /* eventType */, void *eventData) {
12630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      auto *state = static_cast<CallbackState *>(eventData);
12730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      EventLoopManagerSingleton::get()->getWifiRequestManager()
12830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol          .handleScanMonitorStateChangeSync(state->enabled, state->errorCode);
12930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      memoryFree(state);
13030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    };
13130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
13219b9a23f49844d0334780be8eaf339d6065d2a36Andrew Rossignol    bool callbackDeferred = EventLoopManagerSingleton::get()->deferCallback(
133a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie        SystemCallbackType::WifiScanMonitorStateChange, cbState, callback);
13419b9a23f49844d0334780be8eaf339d6065d2a36Andrew Rossignol    if (!callbackDeferred) {
13519b9a23f49844d0334780be8eaf339d6065d2a36Andrew Rossignol      memoryFree(cbState);
13619b9a23f49844d0334780be8eaf339d6065d2a36Andrew Rossignol    }
13730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
138cbff0ad0e40b03ea9972e3446f1d238796e07398Andrew Rossignol}
139cbff0ad0e40b03ea9972e3446f1d238796e07398Andrew Rossignol
140d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignolvoid WifiRequestManager::handleScanResponse(bool pending,
141d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol                                            uint8_t errorCode) {
14284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  struct CallbackState {
14384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    bool pending;
14484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    uint8_t errorCode;
14584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  };
14684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
147a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie  auto *cbState = memoryAlloc<CallbackState>();
148a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie  if (cbState == nullptr) {
14984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    LOGE("Failed to allocate callback state for wifi scan response");
15084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  } else {
151a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie    cbState->pending = pending;
152a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie    cbState->errorCode = errorCode;
15384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
15496f33751ce98a3e64d90373a3a42f88458b3aef0Andrew Rossignol    auto callback = [](uint16_t /* eventType */, void *eventData) {
15584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      auto *state = static_cast<CallbackState *>(eventData);
15684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      EventLoopManagerSingleton::get()->getWifiRequestManager()
15784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol          .handleScanResponseSync(state->pending, state->errorCode);
15884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      memoryFree(state);
15984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    };
16084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
16184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    EventLoopManagerSingleton::get()->deferCallback(
162a5b39579dd3fbd8d74d8efd8d6453fbb10490485Brian Duddie        SystemCallbackType::WifiRequestScanResponse, cbState, callback);
16384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
164d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol}
165d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol
166d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignolvoid WifiRequestManager::handleScanEvent(chreWifiScanEvent *event) {
167254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  auto callback = [](uint16_t eventType, void *eventData) {
168254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    chreWifiScanEvent *scanEvent = static_cast<chreWifiScanEvent *>(eventData);
169254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    EventLoopManagerSingleton::get()->getWifiRequestManager()
170254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        .handleScanEventSync(scanEvent);
171254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  };
172254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
173254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  EventLoopManagerSingleton::get()->deferCallback(
174254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      SystemCallbackType::WifiHandleScanEvent, event, callback);
175d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol}
176d74b2f8991a8dfae2e24ccb0cc84264c48731d55Andrew Rossignol
1777e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishigurobool WifiRequestManager::logStateToBuffer(char *buffer, size_t *bufferPos,
1787e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro                                          size_t bufferSize) const {
1797e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro  bool success = debugDumpPrint(buffer, bufferPos, bufferSize, "\nWifi: "
1807e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro                                "scan monitor %s\n", scanMonitorIsEnabled() ?
1817e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro                                "enabled" : "disabled");
1827e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro
1837e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro  success &= debugDumpPrint(buffer, bufferPos, bufferSize,
1847e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro                            " Wifi scan monitor enabled nanoapps:\n");
1857e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro  for (const auto& instanceId : mScanMonitorNanoapps) {
1867e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro    success &= debugDumpPrint(buffer, bufferPos, bufferSize,
1877e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro                              "  nanoappId=%" PRIu32 "\n", instanceId);
1887e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro  }
1897e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro
1907e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro  if (mScanRequestingNanoappInstanceId.has_value()) {
1917e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro    success &= debugDumpPrint(buffer, bufferPos, bufferSize,
1927e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro                              " Wifi request pending nanoappId=%" PRIu32 "\n",
1937e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro                              mScanRequestingNanoappInstanceId.value());
1947e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro  }
1957e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro
1967e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro  success &= debugDumpPrint(buffer, bufferPos, bufferSize,
1977e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro                            " Wifi transition queue:\n");
1987e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro  for (const auto& transition : mScanMonitorStateTransitions) {
1997e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro    success &= debugDumpPrint(buffer, bufferPos, bufferSize,
2007e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro                              "  enable=%s nanoappId=%" PRIu32 "\n",
2017e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro                              transition.enable ? "true" : "false",
2027e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro                              transition.nanoappInstanceId);
2037e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro  }
2047e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro
2057e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro  return success;
2067e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro}
2077e76ba4dbeea9ea33132bf31b7c3887284c4bd87Arthur Ishiguro
20830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::scanMonitorIsEnabled() const {
20930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return !mScanMonitorNanoapps.empty();
21030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
21130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
21230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::nanoappHasScanMonitorRequest(
21330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    uint32_t instanceId, size_t *nanoappIndex) const {
21430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  size_t index = mScanMonitorNanoapps.find(instanceId);
21544b56ef8ab3ef4de08f2fc84e469dfb3e84e8d08Andrew Rossignol  bool hasScanMonitorRequest = (index != mScanMonitorNanoapps.size());
21630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (hasScanMonitorRequest && nanoappIndex != nullptr) {
21730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    *nanoappIndex = index;
21830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
21930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
22030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return hasScanMonitorRequest;
22130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
22230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
22330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::scanMonitorIsInRequestedState(
22430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    bool requestedState, bool nanoappHasRequest) const {
22530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return (requestedState == scanMonitorIsEnabled() || (!requestedState
22630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      && (!nanoappHasRequest || mScanMonitorNanoapps.size() > 1)));
22730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
22830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
22930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::scanMonitorStateTransitionIsRequired(
23030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    bool requestedState, bool nanoappHasRequest) const {
23130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return ((requestedState && mScanMonitorNanoapps.empty())
23230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      || (!requestedState && nanoappHasRequest
23330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol              && mScanMonitorNanoapps.size() == 1));
23430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
23530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
23630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::addScanMonitorRequestToQueue(Nanoapp *nanoapp,
23730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                      bool enable,
23830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                      const void *cookie) {
23930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  ScanMonitorStateTransition scanMonitorStateTransition;
24030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  scanMonitorStateTransition.nanoappInstanceId = nanoapp->getInstanceId();
24130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  scanMonitorStateTransition.cookie = cookie;
24230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  scanMonitorStateTransition.enable = enable;
24330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
24430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool success = mScanMonitorStateTransitions.push(scanMonitorStateTransition);
24530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!success) {
24630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    LOGW("Too many scan monitor state transitions");
24730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
24830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
24930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return success;
25030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
25130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
25230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::updateNanoappScanMonitoringList(bool enable,
25330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                         uint32_t instanceId) {
25430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool success = true;
25550d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol  Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
25650d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol      .findNanoappByInstanceId(instanceId);
257254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  if (nanoapp == nullptr) {
258254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    CHRE_ASSERT_LOG(false, "Failed to update scan monitoring list for "
259254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol                    "non-existent nanoapp");
26030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  } else {
261254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    size_t nanoappIndex;
262254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    bool hasExistingRequest = nanoappHasScanMonitorRequest(instanceId,
263254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol                                                           &nanoappIndex);
264254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    if (enable) {
265254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      if (!hasExistingRequest) {
266254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        success = nanoapp->registerForBroadcastEvent(
267254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol            CHRE_EVENT_WIFI_SCAN_RESULT);
268254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        if (!success) {
269254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          LOGE("Failed to register nanoapp for wifi scan events");
270254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        } else {
271254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          // The scan monitor was successfully enabled for this nanoapp and
272254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          // there is no existing request. Add it to the list of scan monitoring
273254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          // nanoapps.
274254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          success = mScanMonitorNanoapps.push_back(instanceId);
275254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          if (!success) {
276254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol            nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
277254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol            LOGE("Failed to add nanoapp to the list of scan monitoring "
278254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol                 "nanoapps");
279254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol          }
280254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        }
281254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      }
28230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    } else {
283254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      if (!hasExistingRequest) {
284254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        success = false;
285254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        LOGE("Received a scan monitor state change for a non-existent nanoapp");
286254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      } else {
287254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        // The scan monitor was successfully disabled for a previously enabled
288254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        // nanoapp. Remove it from the list of scan monitoring nanoapps.
289254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        mScanMonitorNanoapps.erase(nanoappIndex);
290254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
291254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      }
29230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
29330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
29430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
29530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return success;
29630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
29730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
29830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolbool WifiRequestManager::postScanMonitorAsyncResultEvent(
29930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
30030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    const void *cookie) {
30130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // Allocate and post an event to the nanoapp requesting wifi.
30230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool eventPosted = false;
30330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!success || updateNanoappScanMonitoringList(enable, nanoappInstanceId)) {
30430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
30530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    if (event == nullptr) {
30630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      LOGE("Failed to allocate wifi scan monitor async result event");
30730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    } else {
30830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->requestType = CHRE_WIFI_REQUEST_TYPE_CONFIGURE_SCAN_MONITOR;
30930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->success = success;
31030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->errorCode = errorCode;
31130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->reserved = 0;
31230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      event->cookie = cookie;
31330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
31430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // Post the event.
31550d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol      eventPosted = EventLoopManagerSingleton::get()->getEventLoop()
31650d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol          .postEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
31750d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol                     kSystemInstanceId, nanoappInstanceId);
3187e2da194710e593ad1248d4fc78b57d71ad01faaAndrew Rossignol      if (!eventPosted) {
3197e2da194710e593ad1248d4fc78b57d71ad01faaAndrew Rossignol        memoryFree(event);
3207e2da194710e593ad1248d4fc78b57d71ad01faaAndrew Rossignol      }
32130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
32230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
32330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
32430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  return eventPosted;
32530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
32630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
32730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolvoid WifiRequestManager::postScanMonitorAsyncResultEventFatal(
32830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    uint32_t nanoappInstanceId, bool success, bool enable, uint8_t errorCode,
32930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    const void *cookie) {
33030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!postScanMonitorAsyncResultEvent(nanoappInstanceId, success, enable,
33130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                       errorCode, cookie)) {
33230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    FATAL_ERROR("Failed to send WiFi scan monitor async result event");
33330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
33430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
33530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
33684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignolbool WifiRequestManager::postScanRequestAsyncResultEvent(
33784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    uint32_t nanoappInstanceId, bool success, uint8_t errorCode,
33884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    const void *cookie) {
33984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  bool eventPosted = false;
34084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  chreAsyncResult *event = memoryAlloc<chreAsyncResult>();
34184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  if (event == nullptr) {
34284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    LOGE("Failed to allocate wifi scan request async result event");
34384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  } else {
34484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->requestType = CHRE_WIFI_REQUEST_TYPE_REQUEST_SCAN;
34584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->success = success;
34684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->errorCode = errorCode;
34784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->reserved = 0;
34884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    event->cookie = cookie;
34984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
35084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    // Post the event.
35150d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol    eventPosted = EventLoopManagerSingleton::get()->getEventLoop()
35250d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol        .postEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
35350d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol                   kSystemInstanceId, nanoappInstanceId);
35484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
35584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
35684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  return eventPosted;
35784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol}
35884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
35984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignolvoid WifiRequestManager::postScanRequestAsyncResultEventFatal(
36084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    uint32_t nanoappInstanceId, bool success, uint8_t errorCode,
36184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    const void *cookie) {
36284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  if (!postScanRequestAsyncResultEvent(nanoappInstanceId, success, errorCode,
36384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                       cookie)) {
36484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    FATAL_ERROR("Failed to send WiFi scan request async result event");
36584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
36684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol}
36784723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
368254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignolvoid WifiRequestManager::postScanEventFatal(chreWifiScanEvent *event) {
36950d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol  bool eventPosted = EventLoopManagerSingleton::get()->getEventLoop()
37050d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol      .postEvent(CHRE_EVENT_WIFI_SCAN_RESULT, event, freeWifiScanEventCallback,
37150d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol                 kSystemInstanceId, kBroadcastInstanceId);
372254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  if (!eventPosted) {
373254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    FATAL_ERROR("Failed to send WiFi scan event");
374254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  }
375254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol}
376254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
37730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignolvoid WifiRequestManager::handleScanMonitorStateChangeSync(bool enabled,
37830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                                          uint8_t errorCode) {
37930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // Success is defined as having no errors ... in life ༼ つ ◕_◕ ༽つ
38030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  bool success = (errorCode == CHRE_ERROR_NONE);
38130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
3821c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie  // TODO(b/62904616): re-enable this assertion
3831c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie  //CHRE_ASSERT_LOG(!mScanMonitorStateTransitions.empty(),
3841c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie  //                "handleScanMonitorStateChangeSync called with no transitions");
3851c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie  if (mScanMonitorStateTransitions.empty()) {
3861c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie    LOGE("WiFi PAL error: handleScanMonitorStateChangeSync called with no "
3871c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie         "transitions (enabled %d errorCode %" PRIu8 ")", enabled, errorCode);
3881c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie  }
3891c815825047c0a8974f4d59fd6120766eca672d0Brian Duddie
39030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  // Always check the front of the queue.
39130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  if (!mScanMonitorStateTransitions.empty()) {
39230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    const auto& stateTransition = mScanMonitorStateTransitions.front();
39330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    success &= (stateTransition.enable == enabled);
39430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
39530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                         success, stateTransition.enable,
39630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                         errorCode, stateTransition.cookie);
39730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    mScanMonitorStateTransitions.pop();
39830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
39930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
40030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  while (!mScanMonitorStateTransitions.empty()) {
40130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    const auto& stateTransition = mScanMonitorStateTransitions.front();
40230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    bool hasScanMonitorRequest = nanoappHasScanMonitorRequest(
40330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        stateTransition.nanoappInstanceId);
40430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    if (scanMonitorIsInRequestedState(
40530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        stateTransition.enable, hasScanMonitorRequest)) {
40630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // We are already in the target state so just post an event indicating
40730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      // success
40830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
40930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                           success, stateTransition.enable,
41030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                           errorCode, stateTransition.cookie);
41130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    } else if (scanMonitorStateTransitionIsRequired(
41230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        stateTransition.enable, hasScanMonitorRequest)) {
41330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      if (mPlatformWifi.configureScanMonitor(stateTransition.enable)) {
41430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        break;
41530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      } else {
41630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol        postScanMonitorAsyncResultEventFatal(stateTransition.nanoappInstanceId,
41730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                             false /* success */,
41830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                             stateTransition.enable, CHRE_ERROR,
41930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol                                             stateTransition.cookie);
42030f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      }
42130f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    } else {
42230f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      CHRE_ASSERT_LOG(false, "Invalid scan monitor state");
42330f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol      break;
42430f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    }
42530f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
42630f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol    mScanMonitorStateTransitions.pop();
42730f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol  }
42830f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol}
42930f18903edc1dfe46e12b9989760ef7a56cb31d3Andrew Rossignol
43084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignolvoid WifiRequestManager::handleScanResponseSync(bool pending,
43184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                                uint8_t errorCode) {
4328d9496f567bf2805c3f95ea5453ec2902f3ec289Meng-hsuan Chung  // TODO(b/65206783): re-enable this assertion
4338d9496f567bf2805c3f95ea5453ec2902f3ec289Meng-hsuan Chung  //CHRE_ASSERT_LOG(mScanRequestingNanoappInstanceId.has_value(),
4348d9496f567bf2805c3f95ea5453ec2902f3ec289Meng-hsuan Chung  //                "handleScanResponseSync called with no outstanding request");
4358d9496f567bf2805c3f95ea5453ec2902f3ec289Meng-hsuan Chung  if (!mScanRequestingNanoappInstanceId.has_value()) {
4368d9496f567bf2805c3f95ea5453ec2902f3ec289Meng-hsuan Chung    LOGE("handleScanResponseSync called with no outstanding request");
4378d9496f567bf2805c3f95ea5453ec2902f3ec289Meng-hsuan Chung  }
4388d9496f567bf2805c3f95ea5453ec2902f3ec289Meng-hsuan Chung
439dc8df2f81cdd3b11d6fec1d02ef9cb746deb2837Meng-hsuan Chung  // TODO: raise this to CHRE_ASSERT_LOG
440dc8df2f81cdd3b11d6fec1d02ef9cb746deb2837Meng-hsuan Chung  if (!pending && errorCode == CHRE_ERROR_NONE) {
441dc8df2f81cdd3b11d6fec1d02ef9cb746deb2837Meng-hsuan Chung    LOGE("Invalid wifi scan response");
442dc8df2f81cdd3b11d6fec1d02ef9cb746deb2837Meng-hsuan Chung    errorCode = CHRE_ERROR;
443dc8df2f81cdd3b11d6fec1d02ef9cb746deb2837Meng-hsuan Chung  }
444dc8df2f81cdd3b11d6fec1d02ef9cb746deb2837Meng-hsuan Chung
44584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  if (mScanRequestingNanoappInstanceId.has_value()) {
44684723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    bool success = (pending && errorCode == CHRE_ERROR_NONE);
447dc8df2f81cdd3b11d6fec1d02ef9cb746deb2837Meng-hsuan Chung    if (!success) {
448dc8df2f81cdd3b11d6fec1d02ef9cb746deb2837Meng-hsuan Chung      LOGW("Wifi scan request failed: pending %d, errorCode %" PRIu8,
449dc8df2f81cdd3b11d6fec1d02ef9cb746deb2837Meng-hsuan Chung           pending, errorCode);
450dc8df2f81cdd3b11d6fec1d02ef9cb746deb2837Meng-hsuan Chung    }
45184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    postScanRequestAsyncResultEventFatal(*mScanRequestingNanoappInstanceId,
45284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                         success, errorCode,
45384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol                                         mScanRequestingNanoappCookie);
454254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
455254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    // Set a flag to indicate that results may be pending.
456254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    mScanRequestResultsArePending = pending;
457254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
458254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    if (pending) {
45950d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol      Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
46050d7d95f1d8cae0e9c6202086b9bd432adff7bf1Andrew Rossignol          .findNanoappByInstanceId(*mScanRequestingNanoappInstanceId);
461254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      if (nanoapp == nullptr) {
462254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        CHRE_ASSERT_LOG(false, "Received WiFi scan response for unknown "
463254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol                        "nanoapp");
464254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      } else {
465254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol        nanoapp->registerForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
466254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      }
467254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    } else {
46884723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      // If the scan results are not pending, clear the nanoapp instance ID.
46984723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      // Otherwise, wait for the results to be delivered and then clear the
47084723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      // instance ID.
47184723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol      mScanRequestingNanoappInstanceId.reset();
47284723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol    }
47384723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol  }
47484723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol}
47584723e6849eb2d8e08557d57d787c5ab7ba01982Andrew Rossignol
476254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignolvoid WifiRequestManager::handleScanEventSync(chreWifiScanEvent *event) {
47771489dd53096ad835ae0aa4899a4c738041253a2Andrew Rossignol  postScanEventFatal(event);
47871489dd53096ad835ae0aa4899a4c738041253a2Andrew Rossignol}
47971489dd53096ad835ae0aa4899a4c738041253a2Andrew Rossignol
48071489dd53096ad835ae0aa4899a4c738041253a2Andrew Rossignolvoid WifiRequestManager::handleFreeWifiScanEvent(chreWifiScanEvent *scanEvent) {
481254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  if (mScanRequestResultsArePending) {
482254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    // Reset the event distribution logic once an entire scan event has been
48371489dd53096ad835ae0aa4899a4c738041253a2Andrew Rossignol    // received and processed by the nanoapp requesting the scan event.
48471489dd53096ad835ae0aa4899a4c738041253a2Andrew Rossignol    mScanEventResultCountAccumulator += scanEvent->resultCount;
48571489dd53096ad835ae0aa4899a4c738041253a2Andrew Rossignol    if (mScanEventResultCountAccumulator >= scanEvent->resultTotal) {
486254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      mScanEventResultCountAccumulator = 0;
487254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      mScanRequestResultsArePending = false;
488254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    }
489254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
49093ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung    if (!mScanRequestResultsArePending
49193ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung        && mScanRequestingNanoappInstanceId.has_value()) {
49293ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung      Nanoapp *nanoapp = EventLoopManagerSingleton::get()->getEventLoop()
49393ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung          .findNanoappByInstanceId(*mScanRequestingNanoappInstanceId);
49493ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung      if (nanoapp == nullptr) {
49593ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung        CHRE_ASSERT_LOG(false, "Attempted to unsubscribe unknown nanoapp from "
49693ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung                        "WiFi scan events");
49793ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung      } else if (!nanoappHasScanMonitorRequest(
49893ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung          *mScanRequestingNanoappInstanceId)) {
49993ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung        nanoapp->unregisterForBroadcastEvent(CHRE_EVENT_WIFI_SCAN_RESULT);
50093ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung      }
501254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
50293ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung      mScanRequestingNanoappInstanceId.reset();
503254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol    }
504254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  }
50593ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung
50693ef03b4649972d24b1ec4695edc5eb38ecc6e3fMeng-hsuan Chung  mPlatformWifi.releaseScanEvent(scanEvent);
507254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol}
508254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
509254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignolvoid WifiRequestManager::freeWifiScanEventCallback(uint16_t eventType,
510254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol                                                   void *eventData) {
511254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  chreWifiScanEvent *scanEvent = static_cast<chreWifiScanEvent *>(eventData);
512254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol  EventLoopManagerSingleton::get()->getWifiRequestManager()
513254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol      .handleFreeWifiScanEvent(scanEvent);
514254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol}
515254795cf8e20f1187367924af8ae7967e6052f9bAndrew Rossignol
51656b7c22b1e7405d8075b6c8e4985f5d17e981d53Andrew Rossignol}  // namespace chre
517