1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16#include "wificond/scanning/offload/offload_scan_manager.h" 17 18#include <vector> 19 20#include <android-base/logging.h> 21 22#include "wificond/scanning/offload/hidl_call_util.h" 23#include "wificond/scanning/offload/offload_scan_utils.h" 24#include "wificond/scanning/offload/offload_service_utils.h" 25#include "wificond/scanning/offload/scan_stats.h" 26#include "wificond/scanning/scan_result.h" 27 28using ::android::hardware::hidl_vec; 29using android::hardware::wifi::offload::V1_0::IOffload; 30using android::hardware::wifi::offload::V1_0::ScanResult; 31using android::hardware::wifi::offload::V1_0::ScanFilter; 32using android::hardware::wifi::offload::V1_0::ScanParam; 33using android::hardware::wifi::offload::V1_0::ScanStats; 34using android::hardware::wifi::offload::V1_0::OffloadStatus; 35using android::hardware::wifi::offload::V1_0::OffloadStatusCode; 36 37using android::wificond::OffloadCallback; 38using ::com::android::server::wifi::wificond::NativeScanResult; 39using ::com::android::server::wifi::wificond::NativeScanStats; 40using std::vector; 41using std::weak_ptr; 42using std::shared_ptr; 43 44using namespace std::placeholders; 45 46namespace { 47const uint32_t kSubscriptionDelayMs = 5000; 48} 49 50namespace android { 51namespace wificond { 52 53OffloadCallbackHandlersImpl::OffloadCallbackHandlersImpl( 54 OffloadScanManager* offload_scan_manager) 55 : offload_scan_manager_(offload_scan_manager) {} 56 57OffloadCallbackHandlersImpl::~OffloadCallbackHandlersImpl() {} 58 59void OffloadCallbackHandlersImpl::OnScanResultHandler( 60 const vector<ScanResult>& scanResult) { 61 if (offload_scan_manager_ != nullptr) { 62 offload_scan_manager_->ReportScanResults(scanResult); 63 } 64} 65 66void OffloadCallbackHandlersImpl::OnErrorHandler(const OffloadStatus& status) { 67 if (offload_scan_manager_ != nullptr) { 68 offload_scan_manager_->ReportError(status); 69 } 70} 71 72OffloadScanManager::OffloadScanManager( 73 weak_ptr<OffloadServiceUtils> utils, 74 shared_ptr<OffloadScanCallbackInterface> callback) 75 : wifi_offload_hal_(nullptr), 76 wifi_offload_callback_(nullptr), 77 death_recipient_(nullptr), 78 offload_status_(OffloadScanManager::kError), 79 service_available_(false), 80 offload_service_utils_(utils), 81 offload_callback_handlers_(new OffloadCallbackHandlersImpl(this)), 82 event_callback_(callback) { 83 if (InitService()) { 84 offload_status_ = OffloadScanManager::kNoError; 85 } 86} 87 88bool OffloadScanManager::InitService() { 89 wifi_offload_hal_ = offload_service_utils_.lock()->GetOffloadService(); 90 if (wifi_offload_hal_ == nullptr) { 91 LOG(ERROR) << "No Offload Service available"; 92 return false; 93 } 94 95 death_recipient_ = offload_service_utils_.lock()->GetOffloadDeathRecipient( 96 std::bind(&OffloadScanManager::OnObjectDeath, this, _1)); 97 uint64_t cookie = reinterpret_cast<uint64_t>(wifi_offload_hal_.get()); 98 99 auto link_to_death_status = 100 wifi_offload_hal_->linkToDeath(death_recipient_, cookie); 101 if (!link_to_death_status.isOk()) { 102 LOG(ERROR) << "Unable to register death handler " 103 << link_to_death_status.description(); 104 return false; 105 } 106 107 wifi_offload_callback_ = offload_service_utils_.lock()->GetOffloadCallback( 108 offload_callback_handlers_.get()); 109 if (wifi_offload_callback_ == nullptr) { 110 LOG(ERROR) << "Invalid Offload callback object"; 111 return false; 112 } 113 114 auto set_callback_status = 115 wifi_offload_hal_->setEventCallback(wifi_offload_callback_); 116 if (!set_callback_status.isOk()) { 117 LOG(ERROR) << "Unable to set event callback for Offload HAL"; 118 return false; 119 } 120 121 service_available_ = true; 122 return true; 123} 124 125bool OffloadScanManager::InitServiceIfNeeded() { 126 if (!service_available_) { 127 return InitService(); 128 } 129 return true; 130} 131 132bool OffloadScanManager::stopScan(OffloadScanManager::ReasonCode* reason_code) { 133 if (!InitServiceIfNeeded() || 134 (getOffloadStatus() != OffloadScanManager::kNoError)) { 135 *reason_code = OffloadScanManager::kNotAvailable; 136 return false; 137 } 138 const auto& res = wifi_offload_hal_->unsubscribeScanResults(); 139 if (!res.isOk()) { 140 *reason_code = OffloadScanManager::kTransactionFailed; 141 LOG(WARNING) << "unsubscribeScanResults() failed " << res.description(); 142 return false; 143 } 144 *reason_code = OffloadScanManager::kNone; 145 return true; 146} 147 148bool OffloadScanManager::GetScanStats(NativeScanStats* native_scan_stats) { 149 const auto& result = HIDL_INVOKE(wifi_offload_hal_, getScanStats); 150 const auto& offload_status_and_scan_stats = result.first; 151 bool transport_status = result.second; 152 if (!transport_status) { 153 return false; 154 } 155 OffloadStatus offload_status = offload_status_and_scan_stats.first; 156 ScanStats scan_stats = offload_status_and_scan_stats.second; 157 if (offload_status.code != OffloadStatusCode::OK) { 158 LOG(WARNING) << offload_status.description; 159 return false; 160 } 161 *native_scan_stats = OffloadScanUtils::convertToNativeScanStats(scan_stats); 162 return true; 163} 164 165bool OffloadScanManager::VerifyAndConvertHIDLStatus( 166 std::pair<OffloadStatus, bool> result, 167 OffloadScanManager::ReasonCode* reason_code) { 168 const auto& offload_status = result.first; 169 bool transport_status = result.second; 170 if (!transport_status) { 171 *reason_code = OffloadScanManager::kTransactionFailed; 172 return false; 173 } 174 if (offload_status.code != OffloadStatusCode::OK) { 175 LOG(WARNING) << offload_status.description; 176 *reason_code = OffloadScanManager::kOperationFailed; 177 return false; 178 } 179 return true; 180} 181 182bool OffloadScanManager::startScan( 183 uint32_t interval_ms, int32_t rssi_threshold, 184 const vector<vector<uint8_t>>& scan_ssids, 185 const vector<vector<uint8_t>>& match_ssids, 186 const vector<uint8_t>& match_security, const vector<uint32_t>& freqs, 187 OffloadScanManager::ReasonCode* reason_code) { 188 if (!InitServiceIfNeeded() || 189 getOffloadStatus() != OffloadScanManager::kNoError) { 190 *reason_code = OffloadScanManager::kNotAvailable; 191 LOG(WARNING) << "Offload HAL scans are not available"; 192 return false; 193 } 194 ScanParam param = 195 OffloadScanUtils::createScanParam(scan_ssids, freqs, interval_ms); 196 ScanFilter filter = OffloadScanUtils::createScanFilter( 197 match_ssids, match_security, rssi_threshold); 198 199 if (!ConfigureScans(param, filter, reason_code)) { 200 return false; 201 } 202 203 if (!SubscribeScanResults(reason_code)) { 204 return false; 205 } 206 207 *reason_code = OffloadScanManager::kNone; 208 return true; 209} 210 211bool OffloadScanManager::ConfigureScans( 212 ScanParam param, ScanFilter filter, 213 OffloadScanManager::ReasonCode* reason_code) { 214 const auto& result = 215 HIDL_INVOKE(wifi_offload_hal_, configureScans, param, filter); 216 if (!VerifyAndConvertHIDLStatus(result, reason_code)) { 217 return false; 218 } 219 return true; 220} 221 222bool OffloadScanManager::SubscribeScanResults( 223 OffloadScanManager::ReasonCode* reason_code) { 224 const auto& result = HIDL_INVOKE(wifi_offload_hal_, subscribeScanResults, 225 kSubscriptionDelayMs); 226 if (!VerifyAndConvertHIDLStatus(result, reason_code)) { 227 return false; 228 } 229 return true; 230} 231 232OffloadScanManager::StatusCode OffloadScanManager::getOffloadStatus() const { 233 if (!service_available_) { 234 return OffloadScanManager::kNoService; 235 } 236 return offload_status_; 237} 238 239bool OffloadScanManager::getScanResults( 240 std::vector<NativeScanResult>* out_scan_results) { 241 for (const auto& scan_result : cached_scan_results_) { 242 out_scan_results->push_back(scan_result); 243 } 244 return true; 245} 246 247bool OffloadScanManager::getScanStats(NativeScanStats* native_scan_stats) { 248 if (!InitServiceIfNeeded()) { 249 LOG(ERROR) << "Offload HAL service unavailable"; 250 return false; 251 } 252 if (getOffloadStatus() != OffloadScanManager::kNoError) { 253 LOG(WARNING) << "Unable to get scan stats due to Wifi Offload HAL error"; 254 return false; 255 } 256 return GetScanStats(native_scan_stats); 257} 258 259OffloadScanManager::~OffloadScanManager() { 260 if (wifi_offload_hal_ != nullptr) { 261 wifi_offload_hal_->unlinkToDeath(death_recipient_); 262 } 263} 264 265void OffloadScanManager::ReportScanResults( 266 const vector<ScanResult>& scanResult) { 267 cached_scan_results_.clear(); 268 if (!OffloadScanUtils::convertToNativeScanResults(scanResult, 269 &cached_scan_results_)) { 270 LOG(WARNING) << "Unable to convert scan results to native format"; 271 return; 272 } 273 if (event_callback_ != nullptr) { 274 event_callback_->OnOffloadScanResult(); 275 } else { 276 LOG(WARNING) 277 << "No callback to report Offload HAL's scan results to wificond"; 278 } 279} 280 281void OffloadScanManager::ReportError(const OffloadStatus& status) { 282 OffloadStatusCode status_code = status.code; 283 OffloadScanManager::StatusCode status_result = OffloadScanManager::kNoError; 284 switch (status_code) { 285 case OffloadStatusCode::OK: 286 status_result = OffloadScanManager::kNoError; 287 break; 288 case OffloadStatusCode::TIMEOUT: 289 status_result = OffloadScanManager::kTimeOut; 290 break; 291 case OffloadStatusCode::NO_CONNECTION: 292 status_result = OffloadScanManager::kNotConnected; 293 break; 294 case OffloadStatusCode::ERROR: 295 status_result = OffloadScanManager::kError; 296 break; 297 default: 298 LOG(WARNING) << "Invalid Offload Error reported"; 299 return; 300 } 301 if (status_result != OffloadScanManager::kNoError) { 302 LOG(WARNING) << "Offload Error reported " << status.description; 303 if (event_callback_ != nullptr) { 304 event_callback_->OnOffloadError( 305 OffloadScanCallbackInterface::REMOTE_FAILURE); 306 } else { 307 LOG(WARNING) << "No callback to report Offload HAL Errors to wificond"; 308 } 309 } 310 offload_status_ = status_result; 311} 312 313void OffloadScanManager::OnObjectDeath(uint64_t cookie) { 314 if (wifi_offload_hal_ == reinterpret_cast<IOffload*>(cookie)) { 315 LOG(ERROR) << "Death Notification for Wifi Offload HAL"; 316 wifi_offload_hal_.clear(); 317 if (event_callback_ != nullptr) { 318 event_callback_->OnOffloadError( 319 OffloadScanCallbackInterface::BINDER_DEATH); 320 } else { 321 LOG(WARNING) 322 << "No callback to report Offload HAL Binder death to wificond"; 323 } 324 service_available_ = false; 325 death_recipient_.clear(); 326 } 327} 328 329} // namespace wificond 330} // namespace android 331