1 #include "offload_server.h" 2 3 #include <android-base/logging.h> 4 #include <chre/apps/wifi_offload/flatbuffers_serialization.h> 5 #include <chre/apps/wifi_offload/host_message_types.h> 6 7 #include "offload_status_util.h" 8 #include "offload_utils.h" 9 10 using namespace android::hardware::wifi::offload::V1_0::implementation::chre_constants; 11 using android::hardware::wifi::offload::V1_0::OffloadStatus; 12 13 namespace { 14 constexpr auto kScanStatsTimeout = std::chrono::milliseconds(500); 15 } 16 17 namespace android { 18 namespace hardware { 19 namespace wifi { 20 namespace offload { 21 namespace V1_0 { 22 namespace implementation { 23 24 class OffloadServer; 25 26 OffloadServer::OffloadServer(ChreInterfaceFactory* factory) 27 : mChreInterfaceCallbacks(new ChreInterfaceCallbacksImpl(this)), 28 mChreInterface(factory->getChreInterface(mChreInterfaceCallbacks.get())) { 29 LOG(VERBOSE) << "Wifi Offload HAL impl"; 30 } 31 32 OffloadStatus OffloadServer::configureScans(const ScanParam& param, const ScanFilter& filter) { 33 LOG(INFO) << "configureScans"; 34 if (!mChreInterface->isConnected()) { 35 return createOffloadStatus(OffloadStatusCode::NO_CONNECTION, 36 "Not connected to hardware implementation"); 37 } 38 wifi_offload::ScanConfig scanConfig; 39 if (!offload_utils::ToChreScanConfig(param, filter, &scanConfig)) { 40 return createOffloadStatus(OffloadStatusCode::ERROR, 41 "Unable to convert scan configuration"); 42 } 43 uint8_t buffer[kMaxMessageLen]; 44 size_t result_size = wifi_offload::fbs::Serialize(scanConfig, buffer, kMaxMessageLen); 45 if (result_size <= 0) { 46 return createOffloadStatus(OffloadStatusCode::ERROR, "Scan config serialization failed"); 47 } 48 std::vector<uint8_t> message(buffer, buffer + result_size); 49 if (!mChreInterface->sendCommandToApp(wifi_offload::HostMessageType::HOST_CMD_CONFIG_SCANS, 50 message)) { 51 return createOffloadStatus(OffloadStatusCode::ERROR, "Unable to send config message"); 52 } 53 return createOffloadStatus(OffloadStatusCode::OK); 54 } 55 56 std::pair<OffloadStatus, ScanStats> OffloadServer::getScanStats() { 57 LOG(INFO) << "getScanStats"; 58 mScanStatsStatus = createOffloadStatus(OffloadStatusCode::OK); 59 if (!mChreInterface->isConnected()) { 60 return {createOffloadStatus(OffloadStatusCode::NO_CONNECTION, "Unable to send scan stats"), 61 {}}; 62 } 63 if (!mChreInterface->sendCommandToApp(wifi_offload::HostMessageType::HOST_CMD_GET_SCAN_STATS, 64 {})) { 65 return {createOffloadStatus(OffloadStatusCode::ERROR, "Unable to send scan stats command"), 66 {}}; 67 } 68 LOG(VERBOSE) << "Sent getScanStats command"; 69 { 70 std::unique_lock<std::mutex> lock(mScanStatsLock); 71 auto timeout_status = mScanStatsCond.wait_for(lock, kScanStatsTimeout); 72 if (timeout_status == std::cv_status::timeout) { 73 std::lock_guard<std::mutex> lock(mOffloadLock); 74 LOG(WARNING) << "Timeout waiting for scan stats"; 75 return {createOffloadStatus(OffloadStatusCode::TIMEOUT, "Scan stats not received"), {}}; 76 } 77 } 78 return std::make_pair(mScanStatsStatus, mScanStats); 79 } 80 81 OffloadStatus OffloadServer::subscribeScanResults(uint32_t delayMs) { 82 LOG(INFO) << "subscribeScanResults with delay:" << delayMs; 83 if (!mChreInterface->isConnected()) { 84 return createOffloadStatus(OffloadStatusCode::NO_CONNECTION, "Not connected to hardware"); 85 } 86 uint32_t* buffer = &delayMs; 87 std::vector<uint8_t> message(reinterpret_cast<uint8_t*>(buffer), 88 reinterpret_cast<uint8_t*>(buffer) + kSubscriptionDelayMsBufLen); 89 if (!mChreInterface->sendCommandToApp( 90 wifi_offload::HostMessageType::HOST_CMD_SUBSCRIBE_SCAN_RESULTS, message)) { 91 return createOffloadStatus(OffloadStatusCode::ERROR, "Unable to request scans"); 92 } 93 return createOffloadStatus(OffloadStatusCode::OK); 94 } 95 96 void OffloadServer::resetNanoApp() { 97 LOG(INFO) << "resetting Nano app"; 98 if (!mChreInterface->isConnected()) { 99 LOG(WARNING) << "Unable to reset nano app, not connected"; 100 return; 101 } 102 if (!mChreInterface->sendCommandToApp(wifi_offload::HostMessageType::HOST_CMD_RESET, {})) { 103 LOG(ERROR) << "Unable to send Reset command to Nano app"; 104 } 105 } 106 107 bool OffloadServer::unsubscribeScanResults() { 108 LOG(INFO) << "unsubscribeScanResults"; 109 if (!mChreInterface->isConnected()) { 110 LOG(WARNING) << "Failed to send unsubscribe scan results message"; 111 return false; 112 } 113 if (!mChreInterface->sendCommandToApp( 114 wifi_offload::HostMessageType::HOST_CMD_UNSUBSCRIBE_SCAN_RESULTS, {})) { 115 LOG(WARNING) << "Failed to send unsubscribe scan results message"; 116 return false; 117 } 118 return true; 119 } 120 121 bool OffloadServer::setEventCallback(const sp<IOffloadCallback>& cb) { 122 LOG(INFO) << "Set Event callback"; 123 if (cb == nullptr) { 124 return false; 125 } 126 std::lock_guard<std::mutex> lock(mOffloadLock); 127 mEventCallback = cb; 128 return true; 129 } 130 131 void OffloadServer::clearEventCallback() { 132 std::lock_guard<std::mutex> lock(mOffloadLock); 133 if (mEventCallback != nullptr) { 134 mEventCallback.clear(); 135 } 136 LOG(INFO) << "Event callback cleared"; 137 } 138 139 void OffloadServer::invokeErrorCallbackAndResetIfNeeded(const OffloadStatus& status) { 140 if (status.code != OffloadStatusCode::OK) { 141 resetNanoApp(); 142 } 143 std::lock_guard<std::mutex> lock(mOffloadLock); 144 if (mEventCallback != nullptr) { 145 mEventCallback->onError(status); 146 } 147 } 148 149 ChreInterfaceCallbacksImpl::ChreInterfaceCallbacksImpl(OffloadServer* server) : mServer(server) { 150 } 151 152 ChreInterfaceCallbacksImpl::~ChreInterfaceCallbacksImpl() { 153 } 154 155 void ChreInterfaceCallbacksImpl::handleConnectionEvents( 156 ChreInterfaceCallbacks::ConnectionEvent event) { 157 switch (event) { 158 case ChreInterfaceCallbacks::ConnectionEvent::DISCONNECTED: 159 case ChreInterfaceCallbacks::ConnectionEvent::CONNECTION_ABORT: { 160 LOG(ERROR) << "Connection to socket lost"; 161 mServer->invokeErrorCallbackAndResetIfNeeded( 162 createOffloadStatus(OffloadStatusCode::NO_CONNECTION, "Connection to socket lost")); 163 } break; 164 case ChreInterfaceCallbacks::ConnectionEvent::CONNECTED: { 165 LOG(INFO) << "Connected to socket"; 166 mServer->invokeErrorCallbackAndResetIfNeeded( 167 createOffloadStatus(OffloadStatusCode::OK)); 168 } break; 169 default: 170 LOG(WARNING) << "Invalid connection event received " << (int)event; 171 break; 172 } 173 } 174 175 void OffloadServer::handleScanResult(const std::vector<uint8_t>& message) { 176 std::vector<wifi_offload::ScanResult> scanResults; 177 std::vector<ScanResult> hidlScanResults; 178 std::string errorMessage; 179 if (!wifi_offload::fbs::Deserialize((uint8_t*)message.data(), message.size(), &scanResults)) { 180 invokeErrorCallbackAndResetIfNeeded( 181 createOffloadStatus(OffloadStatusCode::ERROR, "Cannot deserialize scan results")); 182 return; 183 } 184 if (!offload_utils::ToHidlScanResults(scanResults, &hidlScanResults)) { 185 invokeErrorCallbackAndResetIfNeeded(createOffloadStatus( 186 OffloadStatusCode::ERROR, "Cannot convert scan results to HIDL format")); 187 return; 188 } 189 { 190 std::lock_guard<std::mutex> lock(mOffloadLock); 191 if (mEventCallback != nullptr) { 192 mEventCallback->onScanResult(hidlScanResults); 193 } 194 } 195 } 196 197 void OffloadServer::handleScanStats(const std::vector<uint8_t>& message) { 198 std::lock_guard<std::mutex> lock(mScanStatsLock); 199 wifi_offload::ScanStats stats; 200 OffloadStatus status; 201 // Deserialize scan stats 202 status = createOffloadStatus(OffloadStatusCode::OK); 203 LOG(VERBOSE) << "Received scan stats"; 204 if (!wifi_offload::fbs::Deserialize((uint8_t*)message.data(), message.size(), &stats)) { 205 status = createOffloadStatus(OffloadStatusCode::ERROR, "Cannot deserailize scan stats"); 206 } else if (!offload_utils::ToHidlScanStats(stats, &mScanStats)) { 207 status = createOffloadStatus(OffloadStatusCode::ERROR, 208 "Cannot convert Scan stats to HIDL format"); 209 } 210 mScanStatsStatus = status; 211 mScanStatsCond.notify_all(); 212 } 213 214 void ChreInterfaceCallbacksImpl::handleMessage(uint32_t messageType, 215 const std::vector<uint8_t>& message) { 216 LOG(VERBOSE) << "Message from Nano app " << messageType; 217 switch (messageType) { 218 case wifi_offload::HostMessageType::HOST_MSG_SCAN_RESULTS: { 219 LOG(INFO) << "Received scan results"; 220 mServer->handleScanResult(message); 221 } break; 222 case wifi_offload::HostMessageType::HOST_MSG_SCAN_STATS: 223 LOG(VERBOSE) << "Received scan stats from Nano app"; 224 mServer->handleScanStats(message); 225 break; 226 case wifi_offload::HostMessageType::HOST_MSG_ERROR: 227 LOG(VERBOSE) << "Received error message from Nano app"; 228 { 229 std::string errorMessage; 230 if (offload_utils::ToHidlErrorMessage(message[0], &errorMessage)) { 231 mServer->invokeErrorCallbackAndResetIfNeeded( 232 createOffloadStatus(OffloadStatusCode::ERROR, errorMessage)); 233 } 234 } 235 break; 236 default: 237 LOG(WARNING) << "Unknown message received" << messageType; 238 break; 239 } 240 } 241 242 // Methods from ::android::hidl::base::V1_0::IBase follow. 243 244 } // namespace implementation 245 } // namespace V1_0 246 } // namespace offload 247 } // namespace wifi 248 } // namespace hardware 249 } // namespace android 250