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 17 #include "wificond/scanning/scanner_impl.h" 18 19 #include <string> 20 #include <vector> 21 22 #include <android-base/logging.h> 23 24 #include "wificond/client_interface_impl.h" 25 #include "wificond/scanning/offload/offload_scan_manager.h" 26 #include "wificond/scanning/offload/offload_service_utils.h" 27 #include "wificond/scanning/scan_utils.h" 28 29 using android::binder::Status; 30 using android::net::wifi::IPnoScanEvent; 31 using android::net::wifi::IScanEvent; 32 using android::hardware::wifi::offload::V1_0::IOffload; 33 using android::sp; 34 using com::android::server::wifi::wificond::NativeScanResult; 35 using com::android::server::wifi::wificond::PnoSettings; 36 using com::android::server::wifi::wificond::SingleScanSettings; 37 38 using std::pair; 39 using std::string; 40 using std::vector; 41 using std::weak_ptr; 42 using std::shared_ptr; 43 44 using namespace std::placeholders; 45 46 namespace android { 47 namespace wificond { 48 49 ScannerImpl::ScannerImpl(uint32_t wiphy_index, uint32_t interface_index, 50 const ScanCapabilities& scan_capabilities, 51 const WiphyFeatures& wiphy_features, 52 ClientInterfaceImpl* client_interface, 53 NetlinkUtils* netlink_utils, ScanUtils* scan_utils, 54 weak_ptr<OffloadServiceUtils> offload_service_utils) 55 : valid_(true), 56 scan_started_(false), 57 pno_scan_started_(false), 58 offload_scan_supported_(false), 59 pno_scan_running_over_offload_(false), 60 pno_scan_results_from_offload_(false), 61 wiphy_index_(wiphy_index), 62 interface_index_(interface_index), 63 scan_capabilities_(scan_capabilities), 64 wiphy_features_(wiphy_features), 65 client_interface_(client_interface), 66 netlink_utils_(netlink_utils), 67 scan_utils_(scan_utils), 68 scan_event_handler_(nullptr) { 69 // Subscribe one-shot scan result notification from kernel. 70 LOG(INFO) << "subscribe scan result for interface with index: " 71 << (int)interface_index_; 72 scan_utils_->SubscribeScanResultNotification( 73 interface_index_, 74 std::bind(&ScannerImpl::OnScanResultsReady, this, _1, _2, _3, _4)); 75 // Subscribe scheduled scan result notification from kernel. 76 scan_utils_->SubscribeSchedScanResultNotification( 77 interface_index_, 78 std::bind(&ScannerImpl::OnSchedScanResultsReady, 79 this, 80 _1, _2)); 81 std::shared_ptr<OffloadScanCallbackInterfaceImpl> 82 offload_scan_callback_interface = 83 offload_service_utils.lock()->GetOffloadScanCallbackInterface(this); 84 offload_scan_manager_ = offload_service_utils.lock()->GetOffloadScanManager( 85 offload_service_utils, offload_scan_callback_interface); 86 offload_scan_supported_ = offload_service_utils.lock()->IsOffloadScanSupported(); 87 } 88 89 ScannerImpl::~ScannerImpl() {} 90 91 void ScannerImpl::Invalidate() { 92 LOG(INFO) << "Unsubscribe scan result for interface with index: " 93 << (int)interface_index_; 94 scan_utils_->UnsubscribeScanResultNotification(interface_index_); 95 scan_utils_->UnsubscribeSchedScanResultNotification(interface_index_); 96 } 97 98 bool ScannerImpl::CheckIsValid() { 99 if (!valid_) { 100 LOG(DEBUG) << "Calling on a invalid scanner object." 101 << "Underlying client interface object was destroyed."; 102 } 103 return valid_; 104 } 105 106 Status ScannerImpl::getAvailable2gChannels( 107 std::unique_ptr<vector<int32_t>>* out_frequencies) { 108 if (!CheckIsValid()) { 109 return Status::ok(); 110 } 111 BandInfo band_info; 112 if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info, 113 &scan_capabilities_, &wiphy_features_)) { 114 LOG(ERROR) << "Failed to get wiphy info from kernel"; 115 out_frequencies->reset(nullptr); 116 return Status::ok(); 117 } 118 119 out_frequencies->reset( 120 new vector<int32_t>(band_info.band_2g.begin(), band_info.band_2g.end())); 121 return Status::ok(); 122 } 123 124 Status ScannerImpl::getAvailable5gNonDFSChannels( 125 std::unique_ptr<vector<int32_t>>* out_frequencies) { 126 if (!CheckIsValid()) { 127 return Status::ok(); 128 } 129 BandInfo band_info; 130 if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info, 131 &scan_capabilities_, &wiphy_features_)) { 132 LOG(ERROR) << "Failed to get wiphy info from kernel"; 133 out_frequencies->reset(nullptr); 134 return Status::ok(); 135 } 136 137 out_frequencies->reset( 138 new vector<int32_t>(band_info.band_5g.begin(), band_info.band_5g.end())); 139 return Status::ok(); 140 } 141 142 Status ScannerImpl::getAvailableDFSChannels( 143 std::unique_ptr<vector<int32_t>>* out_frequencies) { 144 if (!CheckIsValid()) { 145 return Status::ok(); 146 } 147 BandInfo band_info; 148 if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info, 149 &scan_capabilities_, &wiphy_features_)) { 150 LOG(ERROR) << "Failed to get wiphy info from kernel"; 151 out_frequencies->reset(nullptr); 152 return Status::ok(); 153 } 154 155 out_frequencies->reset(new vector<int32_t>(band_info.band_dfs.begin(), 156 band_info.band_dfs.end())); 157 return Status::ok(); 158 } 159 160 Status ScannerImpl::getScanResults(vector<NativeScanResult>* out_scan_results) { 161 if (!CheckIsValid()) { 162 return Status::ok(); 163 } 164 if (!scan_utils_->GetScanResult(interface_index_, out_scan_results)) { 165 LOG(ERROR) << "Failed to get scan results via NL80211"; 166 } 167 return Status::ok(); 168 } 169 170 Status ScannerImpl::getPnoScanResults( 171 vector<NativeScanResult>* out_scan_results) { 172 if (!CheckIsValid()) { 173 return Status::ok(); 174 } 175 if (pno_scan_results_from_offload_) { 176 if (!offload_scan_manager_->getScanResults(out_scan_results)) { 177 LOG(ERROR) << "Failed to get scan results via Offload HAL"; 178 } 179 } else { 180 if (!scan_utils_->GetScanResult(interface_index_, out_scan_results)) { 181 LOG(ERROR) << "Failed to get scan results via NL80211"; 182 } 183 } 184 return Status::ok(); 185 } 186 187 Status ScannerImpl::scan(const SingleScanSettings& scan_settings, 188 bool* out_success) { 189 if (!CheckIsValid()) { 190 *out_success = false; 191 return Status::ok(); 192 } 193 194 if (scan_started_) { 195 LOG(WARNING) << "Scan already started"; 196 } 197 // Only request MAC address randomization when station is not associated. 198 bool request_random_mac = wiphy_features_.supports_random_mac_oneshot_scan && 199 !client_interface_->IsAssociated(); 200 201 // Initialize it with an empty ssid for a wild card scan. 202 vector<vector<uint8_t>> ssids = {{}}; 203 204 vector<vector<uint8_t>> skipped_scan_ssids; 205 for (auto& network : scan_settings.hidden_networks_) { 206 if (ssids.size() + 1 > scan_capabilities_.max_num_scan_ssids) { 207 skipped_scan_ssids.emplace_back(network.ssid_); 208 continue; 209 } 210 ssids.push_back(network.ssid_); 211 } 212 213 LogSsidList(skipped_scan_ssids, "Skip scan ssid for single scan"); 214 215 vector<uint32_t> freqs; 216 for (auto& channel : scan_settings.channel_settings_) { 217 freqs.push_back(channel.frequency_); 218 } 219 220 int error_code = 0; 221 if (!scan_utils_->Scan(interface_index_, request_random_mac, ssids, freqs, 222 &error_code)) { 223 CHECK(error_code != ENODEV) << "Driver is in a bad state, restarting wificond"; 224 *out_success = false; 225 return Status::ok(); 226 } 227 scan_started_ = true; 228 *out_success = true; 229 return Status::ok(); 230 } 231 232 Status ScannerImpl::startPnoScan(const PnoSettings& pno_settings, 233 bool* out_success) { 234 pno_settings_ = pno_settings; 235 pno_scan_results_from_offload_ = false; 236 LOG(VERBOSE) << "startPnoScan"; 237 if (offload_scan_supported_ && StartPnoScanOffload(pno_settings)) { 238 // scanning over offload succeeded 239 *out_success = true; 240 } else { 241 *out_success = StartPnoScanDefault(pno_settings); 242 } 243 return Status::ok(); 244 } 245 246 bool ScannerImpl::StartPnoScanOffload(const PnoSettings& pno_settings) { 247 OffloadScanManager::ReasonCode reason_code; 248 vector<vector<uint8_t>> scan_ssids; 249 vector<vector<uint8_t>> match_ssids; 250 vector<uint8_t> match_security; 251 // Empty frequency list: scan all frequencies. 252 vector<uint32_t> freqs; 253 254 ParsePnoSettings(pno_settings, &scan_ssids, &match_ssids, &freqs, 255 &match_security); 256 pno_scan_running_over_offload_ = offload_scan_manager_->startScan( 257 pno_settings.interval_ms_, 258 // TODO: honor both rssi thresholds. 259 pno_settings.min_5g_rssi_, scan_ssids, match_ssids, match_security, freqs, 260 &reason_code); 261 if (pno_scan_running_over_offload_) { 262 LOG(VERBOSE) << "Pno scans requested over Offload HAL"; 263 if (pno_scan_event_handler_ != nullptr) { 264 pno_scan_event_handler_->OnPnoScanOverOffloadStarted(); 265 } 266 } 267 return pno_scan_running_over_offload_; 268 } 269 270 void ScannerImpl::ParsePnoSettings(const PnoSettings& pno_settings, 271 vector<vector<uint8_t>>* scan_ssids, 272 vector<vector<uint8_t>>* match_ssids, 273 vector<uint32_t>* freqs, 274 vector<uint8_t>* match_security) { 275 // TODO provide actionable security match parameters 276 const uint8_t kNetworkFlagsDefault = 0; 277 vector<vector<uint8_t>> skipped_scan_ssids; 278 vector<vector<uint8_t>> skipped_match_ssids; 279 for (auto& network : pno_settings.pno_networks_) { 280 // Add hidden network ssid. 281 if (network.is_hidden_) { 282 // TODO remove pruning for Offload Scans 283 if (scan_ssids->size() + 1 > 284 scan_capabilities_.max_num_sched_scan_ssids) { 285 skipped_scan_ssids.emplace_back(network.ssid_); 286 continue; 287 } 288 scan_ssids->push_back(network.ssid_); 289 } 290 291 if (match_ssids->size() + 1 > scan_capabilities_.max_match_sets) { 292 skipped_match_ssids.emplace_back(network.ssid_); 293 continue; 294 } 295 match_ssids->push_back(network.ssid_); 296 match_security->push_back(kNetworkFlagsDefault); 297 } 298 299 LogSsidList(skipped_scan_ssids, "Skip scan ssid for pno scan"); 300 LogSsidList(skipped_match_ssids, "Skip match ssid for pno scan"); 301 } 302 303 bool ScannerImpl::StartPnoScanDefault(const PnoSettings& pno_settings) { 304 if (!CheckIsValid()) { 305 return false; 306 } 307 if (pno_scan_started_) { 308 LOG(WARNING) << "Pno scan already started"; 309 } 310 // An empty ssid for a wild card scan. 311 vector<vector<uint8_t>> scan_ssids = {{}}; 312 vector<vector<uint8_t>> match_ssids; 313 vector<uint8_t> unused; 314 // Empty frequency list: scan all frequencies. 315 vector<uint32_t> freqs; 316 317 ParsePnoSettings(pno_settings, &scan_ssids, &match_ssids, &freqs, &unused); 318 // Only request MAC address randomization when station is not associated. 319 bool request_random_mac = wiphy_features_.supports_random_mac_sched_scan && 320 !client_interface_->IsAssociated(); 321 322 int error_code = 0; 323 if (!scan_utils_->StartScheduledScan(interface_index_, 324 GenerateIntervalSetting(pno_settings), 325 // TODO: honor both rssi thresholds. 326 pno_settings.min_5g_rssi_, 327 request_random_mac, 328 scan_ssids, 329 match_ssids, 330 freqs, 331 &error_code)) { 332 LOG(ERROR) << "Failed to start pno scan"; 333 CHECK(error_code != ENODEV) << "Driver is in a bad state, restarting wificond"; 334 return false; 335 } 336 LOG(INFO) << "Pno scan started"; 337 pno_scan_started_ = true; 338 return true; 339 } 340 341 Status ScannerImpl::stopPnoScan(bool* out_success) { 342 if (offload_scan_supported_ && StopPnoScanOffload()) { 343 // Pno scans over offload stopped successfully 344 *out_success = true; 345 } else { 346 // Pno scans were not requested over offload 347 *out_success = StopPnoScanDefault(); 348 } 349 return Status::ok(); 350 } 351 352 bool ScannerImpl::StopPnoScanOffload() { 353 OffloadScanManager::ReasonCode reason_code; 354 if (!pno_scan_running_over_offload_) { 355 return false; 356 } 357 if (!offload_scan_manager_->stopScan(&reason_code)) { 358 LOG(WARNING) << "Unable to unsubscribe to Offload scan results"; 359 } 360 pno_scan_running_over_offload_ = false; 361 LOG(VERBOSE) << "Pno scans over Offload stopped"; 362 return true; 363 } 364 365 bool ScannerImpl::StopPnoScanDefault() { 366 if (!CheckIsValid()) { 367 return false; 368 } 369 370 if (!pno_scan_started_) { 371 LOG(WARNING) << "No pno scan started"; 372 } 373 if (!scan_utils_->StopScheduledScan(interface_index_)) { 374 return false; 375 } 376 LOG(INFO) << "Pno scan stopped"; 377 pno_scan_started_ = false; 378 return true; 379 } 380 381 Status ScannerImpl::abortScan() { 382 if (!CheckIsValid()) { 383 return Status::ok(); 384 } 385 386 if (!scan_started_) { 387 LOG(WARNING) << "Scan is not started. Ignore abort request"; 388 return Status::ok(); 389 } 390 if (!scan_utils_->AbortScan(interface_index_)) { 391 LOG(WARNING) << "Abort scan failed"; 392 } 393 return Status::ok(); 394 } 395 396 Status ScannerImpl::subscribeScanEvents(const sp<IScanEvent>& handler) { 397 if (!CheckIsValid()) { 398 return Status::ok(); 399 } 400 401 if (scan_event_handler_ != nullptr) { 402 LOG(ERROR) << "Found existing scan events subscriber." 403 << " This subscription request will unsubscribe it"; 404 } 405 scan_event_handler_ = handler; 406 return Status::ok(); 407 } 408 409 Status ScannerImpl::unsubscribeScanEvents() { 410 scan_event_handler_ = nullptr; 411 return Status::ok(); 412 } 413 414 Status ScannerImpl::subscribePnoScanEvents(const sp<IPnoScanEvent>& handler) { 415 if (!CheckIsValid()) { 416 return Status::ok(); 417 } 418 419 if (pno_scan_event_handler_ != nullptr) { 420 LOG(ERROR) << "Found existing pno scan events subscriber." 421 << " This subscription request will unsubscribe it"; 422 } 423 pno_scan_event_handler_ = handler; 424 425 return Status::ok(); 426 } 427 428 Status ScannerImpl::unsubscribePnoScanEvents() { 429 pno_scan_event_handler_ = nullptr; 430 return Status::ok(); 431 } 432 433 void ScannerImpl::OnScanResultsReady(uint32_t interface_index, bool aborted, 434 vector<vector<uint8_t>>& ssids, 435 vector<uint32_t>& frequencies) { 436 if (!scan_started_) { 437 LOG(INFO) << "Received external scan result notification from kernel."; 438 } 439 scan_started_ = false; 440 if (scan_event_handler_ != nullptr) { 441 // TODO: Pass other parameters back once we find framework needs them. 442 if (aborted) { 443 LOG(WARNING) << "Scan aborted"; 444 scan_event_handler_->OnScanFailed(); 445 } else { 446 scan_event_handler_->OnScanResultReady(); 447 } 448 } else { 449 LOG(WARNING) << "No scan event handler found."; 450 } 451 } 452 453 void ScannerImpl::OnSchedScanResultsReady(uint32_t interface_index, 454 bool scan_stopped) { 455 if (pno_scan_event_handler_ != nullptr) { 456 if (scan_stopped) { 457 // If |pno_scan_started_| is false. 458 // This stop notification might result from our own request. 459 // See the document for NL80211_CMD_SCHED_SCAN_STOPPED in nl80211.h. 460 if (pno_scan_started_) { 461 LOG(WARNING) << "Unexpected pno scan stopped event"; 462 pno_scan_event_handler_->OnPnoScanFailed(); 463 } 464 pno_scan_started_ = false; 465 } else { 466 LOG(INFO) << "Pno scan result ready event"; 467 pno_scan_results_from_offload_ = false; 468 pno_scan_event_handler_->OnPnoNetworkFound(); 469 } 470 } 471 } 472 473 SchedScanIntervalSetting ScannerImpl::GenerateIntervalSetting( 474 const ::com::android::server::wifi::wificond::PnoSettings& 475 pno_settings) const { 476 bool support_num_scan_plans = scan_capabilities_.max_num_scan_plans >= 2; 477 bool support_scan_plan_interval = 478 scan_capabilities_.max_scan_plan_interval * 1000 >= 479 pno_settings.interval_ms_ * PnoSettings::kSlowScanIntervalMultiplier; 480 bool support_scan_plan_iterations = 481 scan_capabilities_.max_scan_plan_iterations >= 482 PnoSettings::kFastScanIterations; 483 484 uint32_t fast_scan_interval = 485 static_cast<uint32_t>(pno_settings.interval_ms_); 486 if (support_num_scan_plans && support_scan_plan_interval && 487 support_scan_plan_iterations) { 488 return SchedScanIntervalSetting{ 489 {{fast_scan_interval, PnoSettings::kFastScanIterations}}, 490 fast_scan_interval * PnoSettings::kSlowScanIntervalMultiplier}; 491 } else { 492 // Device doesn't support the provided scan plans. 493 // Specify single interval instead. 494 // In this case, the driver/firmware is expected to implement back off 495 // logic internally using |pno_settings.interval_ms_| as "fast scan" 496 // interval. 497 return SchedScanIntervalSetting{{}, fast_scan_interval}; 498 } 499 } 500 501 void ScannerImpl::OnOffloadScanResult() { 502 if (!pno_scan_running_over_offload_) { 503 LOG(WARNING) << "Scan results from Offload HAL but scan not requested over " 504 "this interface"; 505 return; 506 } 507 LOG(INFO) << "Offload Scan results received"; 508 pno_scan_results_from_offload_ = true; 509 if (pno_scan_event_handler_ != nullptr) { 510 pno_scan_event_handler_->OnPnoNetworkFound(); 511 } else { 512 LOG(WARNING) << "No scan event handler Offload Scan result"; 513 } 514 } 515 516 void ScannerImpl::OnOffloadError( 517 OffloadScanCallbackInterface::AsyncErrorReason error_code) { 518 if (!pno_scan_running_over_offload_) { 519 // Ignore irrelevant error notifications 520 LOG(WARNING) << "Offload HAL Async Error occured but Offload HAL is not " 521 "subscribed to"; 522 return; 523 } 524 LOG(ERROR) << "Offload Service Async Failure error_code=" << error_code; 525 switch (error_code) { 526 case OffloadScanCallbackInterface::AsyncErrorReason::BINDER_DEATH: 527 LOG(ERROR) << "Binder death"; 528 if (pno_scan_event_handler_ != nullptr) { 529 pno_scan_event_handler_->OnPnoScanOverOffloadFailed( 530 net::wifi::IPnoScanEvent::PNO_SCAN_OVER_OFFLOAD_BINDER_FAILURE); 531 } 532 break; 533 case OffloadScanCallbackInterface::AsyncErrorReason::REMOTE_FAILURE: 534 LOG(ERROR) << "Remote failure"; 535 if (pno_scan_event_handler_ != nullptr) { 536 pno_scan_event_handler_->OnPnoScanOverOffloadFailed( 537 net::wifi::IPnoScanEvent::PNO_SCAN_OVER_OFFLOAD_REMOTE_FAILURE); 538 } 539 break; 540 default: 541 LOG(WARNING) << "Invalid Error code"; 542 break; 543 } 544 bool success = false; 545 // Stop scans over Offload HAL and request them over netlink 546 stopPnoScan(&success); 547 if (success) { 548 LOG(INFO) << "Pno scans stopped"; 549 } 550 // Restart PNO scans over netlink interface 551 success = StartPnoScanDefault(pno_settings_); 552 if (success) { 553 LOG(INFO) << "Pno scans restarted"; 554 } else { 555 LOG(ERROR) << "Unable to fall back to netlink pno scan"; 556 pno_scan_event_handler_->OnPnoScanFailed(); 557 } 558 } 559 560 void ScannerImpl::LogSsidList(vector<vector<uint8_t>>& ssid_list, 561 string prefix) { 562 if (ssid_list.empty()) { 563 return; 564 } 565 string ssid_list_string; 566 for (auto& ssid : ssid_list) { 567 ssid_list_string += string(ssid.begin(), ssid.end()); 568 if (&ssid != &ssid_list.back()) { 569 ssid_list_string += ", "; 570 } 571 } 572 LOG(WARNING) << prefix << ": " << ssid_list_string; 573 } 574 575 } // namespace wificond 576 } // namespace android 577