diff --git a/wifi_offload/offload_server.cpp b/wifi_offload/offload_server.cpp index 56e139a1..877d420a 100644 --- a/wifi_offload/offload_server.cpp +++ b/wifi_offload/offload_server.cpp @@ -8,6 +8,11 @@ #include "offload_utils.h" using namespace android::hardware::wifi::offload::V1_0::implementation::chre_constants; +using android::hardware::wifi::offload::V1_0::OffloadStatus; + +namespace { +constexpr auto kScanStatsTimeout = std::chrono::milliseconds(500); +} namespace android { namespace hardware { @@ -27,7 +32,7 @@ OffloadServer::OffloadServer(ChreInterfaceFactory* factory) OffloadStatus OffloadServer::configureScans(const ScanParam& param, const ScanFilter& filter) { LOG(INFO) << "configureScans"; if (!mChreInterface->isConnected()) { - return createOffloadStatus(OffloadStatusCode::ERROR, + return createOffloadStatus(OffloadStatusCode::NO_CONNECTION, "Not connected to hardware implementation"); } wifi_offload::ScanConfig scanConfig; @@ -50,14 +55,33 @@ OffloadStatus OffloadServer::configureScans(const ScanParam& param, const ScanFi std::pair OffloadServer::getScanStats() { LOG(INFO) << "getScanStats"; - OffloadStatus status = createOffloadStatus(OffloadStatusCode::OK); - return std::make_pair(status, mScanStats); + mScanStatsStatus = createOffloadStatus(OffloadStatusCode::OK); + if (!mChreInterface->isConnected()) { + return {createOffloadStatus(OffloadStatusCode::NO_CONNECTION, "Unable to send scan stats"), + {}}; + } + if (!mChreInterface->sendCommandToApp(wifi_offload::HostMessageType::HOST_CMD_GET_SCAN_STATS, + {})) { + return {createOffloadStatus(OffloadStatusCode::ERROR, "Unable to send scan stats command"), + {}}; + } + LOG(VERBOSE) << "Sent getScanStats command"; + { + std::unique_lock lock(mScanStatsLock); + auto timeout_status = mScanStatsCond.wait_for(lock, kScanStatsTimeout); + if (timeout_status == std::cv_status::timeout) { + std::lock_guard lock(mOffloadLock); + LOG(WARNING) << "Timeout waiting for scan stats"; + return {createOffloadStatus(OffloadStatusCode::TIMEOUT, "Scan stats not received"), {}}; + } + } + return std::make_pair(mScanStatsStatus, mScanStats); } OffloadStatus OffloadServer::subscribeScanResults(uint32_t delayMs) { LOG(INFO) << "subscribeScanResults with delay:" << delayMs; if (!mChreInterface->isConnected()) { - return createOffloadStatus(OffloadStatusCode::ERROR, "Not connected to hardware"); + return createOffloadStatus(OffloadStatusCode::NO_CONNECTION, "Not connected to hardware"); } uint32_t* buffer = &delayMs; std::vector message(reinterpret_cast(buffer), @@ -70,7 +94,6 @@ OffloadStatus OffloadServer::subscribeScanResults(uint32_t delayMs) { } bool OffloadServer::unsubscribeScanResults() { - bool result = false; LOG(INFO) << "unsubscribeScanResults"; if (!mChreInterface->isConnected()) { LOG(WARNING) << "Failed to send unsubscribe scan results message"; @@ -86,21 +109,29 @@ bool OffloadServer::unsubscribeScanResults() { bool OffloadServer::setEventCallback(const sp& cb) { LOG(INFO) << "Set Event callback"; - bool result = false; - if (cb != nullptr) { - mEventCallback = cb; - result = true; + if (cb == nullptr) { + return false; } - return result; + std::lock_guard lock(mOffloadLock); + mEventCallback = cb; + return true; } void OffloadServer::clearEventCallback() { + std::lock_guard lock(mOffloadLock); if (mEventCallback != nullptr) { mEventCallback.clear(); } LOG(INFO) << "Event callback cleared"; } +void OffloadServer::invokeErrorCallback(const OffloadStatus& status) { + std::lock_guard lock(mOffloadLock); + if (mEventCallback != nullptr) { + mEventCallback->onError(status); + } +} + ChreInterfaceCallbacksImpl::ChreInterfaceCallbacksImpl(OffloadServer* server) : mServer(server) { } @@ -109,12 +140,88 @@ ChreInterfaceCallbacksImpl::~ChreInterfaceCallbacksImpl() { void ChreInterfaceCallbacksImpl::handleConnectionEvents( ChreInterfaceCallbacks::ConnectionEvent event) { - LOG(VERBOSE) << "Connection event received " << (int)event; + switch (event) { + case ChreInterfaceCallbacks::ConnectionEvent::DISCONNECTED: + case ChreInterfaceCallbacks::ConnectionEvent::CONNECTION_ABORT: { + LOG(ERROR) << "Connection to socket lost"; + mServer->invokeErrorCallback( + createOffloadStatus(OffloadStatusCode::NO_CONNECTION, "Connection to socket lost")); + } break; + case ChreInterfaceCallbacks::ConnectionEvent::CONNECTED: { + LOG(INFO) << "Connected to socket"; + mServer->invokeErrorCallback(createOffloadStatus(OffloadStatusCode::OK)); + } break; + default: + LOG(WARNING) << "Invalid connection event received " << (int)event; + break; + } +} + +void OffloadServer::handleScanResult(const std::vector& message) { + std::vector scanResults; + std::vector hidlScanResults; + std::string errorMessage; + if (!wifi_offload::fbs::Deserialize((uint8_t*)message.data(), message.size(), &scanResults)) { + invokeErrorCallback( + createOffloadStatus(OffloadStatusCode::ERROR, "Cannot deserialize scan results")); + return; + } + if (!offload_utils::ToHidlScanResults(scanResults, &hidlScanResults)) { + invokeErrorCallback(createOffloadStatus(OffloadStatusCode::ERROR, + "Cannot convert scan results to HIDL format")); + return; + } + { + std::lock_guard lock(mOffloadLock); + if (mEventCallback != nullptr) { + mEventCallback->onScanResult(hidlScanResults); + } + } +} + +void OffloadServer::handleScanStats(const std::vector& message) { + std::lock_guard lock(mScanStatsLock); + wifi_offload::ScanStats stats; + OffloadStatus status; + // Deserialize scan stats + status = createOffloadStatus(OffloadStatusCode::OK); + LOG(VERBOSE) << "Received scan stats"; + if (!wifi_offload::fbs::Deserialize((uint8_t*)message.data(), message.size(), &stats)) { + status = createOffloadStatus(OffloadStatusCode::ERROR, "Cannot deserailize scan stats"); + } else if (!offload_utils::ToHidlScanStats(stats, &mScanStats)) { + status = createOffloadStatus(OffloadStatusCode::ERROR, + "Cannot convert Scan stats to HIDL format"); + } + mScanStatsStatus = status; + mScanStatsCond.notify_all(); } void ChreInterfaceCallbacksImpl::handleMessage(uint32_t messageType, const std::vector& message) { LOG(VERBOSE) << "Message from Nano app " << messageType; + switch (messageType) { + case wifi_offload::HostMessageType::HOST_MSG_SCAN_RESULTS: { + LOG(INFO) << "Received scan results"; + mServer->handleScanResult(message); + } break; + case wifi_offload::HostMessageType::HOST_MSG_SCAN_STATS: + LOG(VERBOSE) << "Received scan stats from Nano app"; + mServer->handleScanStats(message); + break; + case wifi_offload::HostMessageType::HOST_MSG_ERROR: + LOG(VERBOSE) << "Received error message from Nano app"; + { + std::string errorMessage; + if (offload_utils::ToHidlErrorMessage(message[0], &errorMessage)) { + mServer->invokeErrorCallback( + createOffloadStatus(OffloadStatusCode::ERROR, errorMessage)); + } + } + break; + default: + LOG(WARNING) << "Unknown message received" << messageType; + break; + } } // Methods from ::android::hidl::base::V1_0::IBase follow. diff --git a/wifi_offload/offload_server.h b/wifi_offload/offload_server.h index f10ace16..2b150b16 100644 --- a/wifi_offload/offload_server.h +++ b/wifi_offload/offload_server.h @@ -41,7 +41,16 @@ class OffloadServer { void clearEventCallback(); private: + void invokeErrorCallback(const android::hardware::wifi::offload::V1_0::OffloadStatus& status); + void handleScanResult(const std::vector& message); + void handleScanStats(const std::vector& message); + ScanStats mScanStats; + std::mutex mScanStatsLock; + std::condition_variable mScanStatsCond; + std::mutex mOffloadLock; + OffloadStatus mScanStatsStatus; + std::unique_ptr mChreInterfaceCallbacks; std::unique_ptr mChreInterface; sp mEventCallback;