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