Home | History | Annotate | Download | only in scanning
      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