OSDN Git Service

Change abortScan() binder API to void
[android-x86/system-connectivity-wificond.git] / scanning / scanner_impl.cpp
index 12de959..2c1b1d0 100644 (file)
 
 #include <android-base/logging.h>
 
+#include "wificond/client_interface_impl.h"
 #include "wificond/scanning/scan_utils.h"
 
 using android::binder::Status;
 using android::net::wifi::IPnoScanEvent;
 using android::net::wifi::IScanEvent;
-using android::String16;
 using android::sp;
 using com::android::server::wifi::wificond::NativeScanResult;
 using com::android::server::wifi::wificond::PnoSettings;
@@ -40,24 +40,48 @@ using namespace std::placeholders;
 namespace android {
 namespace wificond {
 
-ScannerImpl::ScannerImpl(uint32_t interface_index,
-                         const BandInfo& band_info,
+ScannerImpl::ScannerImpl(uint32_t wiphy_index,
+                         uint32_t interface_index,
                          const ScanCapabilities& scan_capabilities,
                          const WiphyFeatures& wiphy_features,
+                         ClientInterfaceImpl* client_interface,
+                         NetlinkUtils* netlink_utils,
                          ScanUtils* scan_utils)
     : valid_(true),
+      scan_started_(false),
       pno_scan_started_(false),
+      wiphy_index_(wiphy_index),
       interface_index_(interface_index),
-      band_info_(band_info),
       scan_capabilities_(scan_capabilities),
       wiphy_features_(wiphy_features),
+      client_interface_(client_interface),
+      netlink_utils_(netlink_utils),
       scan_utils_(scan_utils),
-      scan_event_handler_(nullptr) {}
+      scan_event_handler_(nullptr) {
+  // Subscribe one-shot scan result notification from kernel.
+  LOG(INFO) << "subscribe scan result for interface with index: "
+            << (int)interface_index_;
+  scan_utils_->SubscribeScanResultNotification(
+      interface_index_,
+      std::bind(&ScannerImpl::OnScanResultsReady,
+                this,
+                _1, _2, _3, _4));
+  // Subscribe scheduled scan result notification from kernel.
+  scan_utils_->SubscribeSchedScanResultNotification(
+      interface_index_,
+      std::bind(&ScannerImpl::OnSchedScanResultsReady,
+                this,
+                _1, _2));
+}
 
 ScannerImpl::~ScannerImpl() {
-  if (scan_event_handler_ != nullptr) {
-    scan_utils_->UnsubscribeScanResultNotification(interface_index_);
-  }
+}
+
+void ScannerImpl::Invalidate() {
+  LOG(INFO) << "Unsubscribe scan result for interface with index: "
+            << (int)interface_index_;
+  scan_utils_->UnsubscribeScanResultNotification(interface_index_);
+  scan_utils_->UnsubscribeSchedScanResultNotification(interface_index_);
 }
 
 bool ScannerImpl::CheckIsValid() {
@@ -68,31 +92,63 @@ bool ScannerImpl::CheckIsValid() {
   return valid_;
 }
 
-Status ScannerImpl::getAvailable2gChannels(vector<int32_t>* out_frequencies) {
+Status ScannerImpl::getAvailable2gChannels(
+    std::unique_ptr<vector<int32_t>>* out_frequencies) {
   if (!CheckIsValid()) {
     return Status::ok();
   }
-  *out_frequencies = vector<int32_t>(band_info_.band_2g.begin(),
-                                     band_info_.band_2g.end());
+  BandInfo band_info;
+  if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
+                               &band_info,
+                               &scan_capabilities_,
+                               &wiphy_features_)) {
+    LOG(ERROR) << "Failed to get wiphy info from kernel";
+    out_frequencies->reset(nullptr);
+    return Status::ok();
+  }
+
+  out_frequencies->reset(new vector<int32_t>(band_info.band_2g.begin(),
+                                             band_info.band_2g.end()));
   return Status::ok();
 }
 
 Status ScannerImpl::getAvailable5gNonDFSChannels(
-    vector<int32_t>* out_frequencies) {
+    std::unique_ptr<vector<int32_t>>* out_frequencies) {
   if (!CheckIsValid()) {
     return Status::ok();
   }
-  *out_frequencies = vector<int32_t>(band_info_.band_5g.begin(),
-                                     band_info_.band_5g.end());
+  BandInfo band_info;
+  if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
+                               &band_info,
+                               &scan_capabilities_,
+                               &wiphy_features_)) {
+    LOG(ERROR) << "Failed to get wiphy info from kernel";
+    out_frequencies->reset(nullptr);
+    return Status::ok();
+  }
+
+  out_frequencies->reset(new vector<int32_t>(band_info.band_5g.begin(),
+                                             band_info.band_5g.end()));
   return Status::ok();
 }
 
-Status ScannerImpl::getAvailableDFSChannels(vector<int32_t>* out_frequencies) {
+Status ScannerImpl::getAvailableDFSChannels(
+    std::unique_ptr<vector<int32_t>>* out_frequencies) {
   if (!CheckIsValid()) {
     return Status::ok();
   }
-  *out_frequencies = vector<int32_t>(band_info_.band_dfs.begin(),
-                                     band_info_.band_dfs.end());
+  BandInfo band_info;
+  if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
+                               &band_info,
+                               &scan_capabilities_,
+                               &wiphy_features_)) {
+    LOG(ERROR) << "Failed to get wiphy info from kernel";
+    out_frequencies->reset(nullptr);
+    return Status::ok();
+  }
+
+  out_frequencies->reset(new vector<int32_t>(band_info.band_dfs.begin(),
+                                             band_info.band_dfs.end()));
   return Status::ok();
 }
 
@@ -109,134 +165,172 @@ Status ScannerImpl::getScanResults(vector<NativeScanResult>* out_scan_results) {
 Status ScannerImpl::scan(const SingleScanSettings& scan_settings,
                          bool* out_success) {
   if (!CheckIsValid()) {
+    *out_success = false;
     return Status::ok();
   }
 
-  bool random_mac =  wiphy_features_.supports_random_mac_oneshot_scan;
-
-  if (scan_settings.is_full_scan_) {
-    if (!scan_utils_->StartFullScan(interface_index_, random_mac)) {
-      *out_success = false;
-      return Status::ok();
-    }
+  if (scan_started_) {
+    LOG(WARNING) << "Scan already started";
   }
+  // Only request MAC address randomization when station is not associated.
+  bool request_random_mac =  wiphy_features_.supports_random_mac_oneshot_scan &&
+      !client_interface_->IsAssociated();
 
   // Initialize it with an empty ssid for a wild card scan.
-  vector<vector<uint8_t>> ssids = {{0}};
+  vector<vector<uint8_t>> ssids = {{}};
+
+  vector<vector<uint8_t>> skipped_scan_ssids;
   for (auto& network : scan_settings.hidden_networks_) {
+    if (ssids.size() + 1 > scan_capabilities_.max_num_scan_ssids) {
+      skipped_scan_ssids.emplace_back(network.ssid_);
+      continue;
+    }
     ssids.push_back(network.ssid_);
   }
+
+  LogSsidList(skipped_scan_ssids, "Skip scan ssid for single scan");
+
   vector<uint32_t> freqs;
   for (auto& channel : scan_settings.channel_settings_) {
     freqs.push_back(channel.frequency_);
   }
 
-  if (!scan_utils_->Scan(interface_index_, random_mac, ssids, freqs)) {
+  if (!scan_utils_->Scan(interface_index_, request_random_mac, ssids, freqs)) {
     *out_success = false;
-    LOG(ERROR) << "Failed to start a scan";
     return Status::ok();
   }
+  scan_started_ = true;
   *out_success = true;
   return Status::ok();
 }
 
 Status ScannerImpl::startPnoScan(const PnoSettings& pno_settings,
                                  bool* out_success) {
-  if (pno_scan_started_) {
-    LOG(ERROR) << "Pno scan already started";
+  if (!CheckIsValid()) {
     *out_success = false;
     return Status::ok();
   }
+  if (pno_scan_started_) {
+    LOG(WARNING) << "Pno scan already started";
+  }
   // An empty ssid for a wild card scan.
-  vector<vector<uint8_t>> scan_ssids = {{0}};
+  vector<vector<uint8_t>> scan_ssids = {{}};
   vector<vector<uint8_t>> match_ssids;
   // Empty frequency list: scan all frequencies.
   vector<uint32_t> freqs;
 
+  vector<vector<uint8_t>> skipped_scan_ssids;
+  vector<vector<uint8_t>> skipped_match_ssids;
   for (auto& network : pno_settings.pno_networks_) {
-    match_ssids.push_back(network.ssid_);
     // Add hidden network ssid.
     if (network.is_hidden_) {
+      if (scan_ssids.size() + 1 > scan_capabilities_.max_num_sched_scan_ssids) {
+        skipped_scan_ssids.emplace_back(network.ssid_);
+        continue;
+      }
       scan_ssids.push_back(network.ssid_);
     }
+
+    if (match_ssids.size() + 1 > scan_capabilities_.max_match_sets) {
+      skipped_match_ssids.emplace_back(network.ssid_);
+      continue;
+    }
+    match_ssids.push_back(network.ssid_);
   }
-  bool random_mac = wiphy_features_.supports_random_mac_sched_scan;
+
+  LogSsidList(skipped_scan_ssids, "Skip scan ssid for pno scan");
+  LogSsidList(skipped_match_ssids, "Skip match ssid for pno scan");
+
+  // Only request MAC address randomization when station is not associated.
+  bool request_random_mac = wiphy_features_.supports_random_mac_sched_scan &&
+      !client_interface_->IsAssociated();
 
   if (!scan_utils_->StartScheduledScan(interface_index_,
                                        pno_settings.interval_ms_,
                                        // TODO: honor both rssi thresholds.
-                                       pno_settings.min_2g_rssi_,
-                                       random_mac,
+                                       pno_settings.min_5g_rssi_,
+                                       request_random_mac,
                                        scan_ssids,
                                        match_ssids,
                                        freqs)) {
     *out_success = false;
-    LOG(ERROR) << "Failed to start scheduled scan";
+    LOG(ERROR) << "Failed to start pno scan";
     return Status::ok();
   }
+  LOG(INFO) << "Pno scan started";
   pno_scan_started_ = true;
   *out_success = true;
   return Status::ok();
 }
 
 Status ScannerImpl::stopPnoScan(bool* out_success) {
-  if (!pno_scan_started_) {
-    LOG(ERROR) << "No pno scan started";
+  if (!CheckIsValid()) {
     *out_success = false;
     return Status::ok();
   }
+
+  if (!pno_scan_started_) {
+    LOG(WARNING) << "No pno scan started";
+  }
   if (!scan_utils_->StopScheduledScan(interface_index_)) {
     *out_success = false;
     return Status::ok();
   }
+  LOG(INFO) << "Pno scan stopped";
   pno_scan_started_ = false;
   *out_success = true;
   return Status::ok();
 }
 
+Status ScannerImpl::abortScan() {
+  if (!CheckIsValid()) {
+    return Status::ok();
+  }
+
+  if (!scan_started_) {
+    LOG(WARNING) << "Scan is not started. Ignore abort request";
+    return Status::ok();
+  }
+  if (!scan_utils_->AbortScan(interface_index_)) {
+    LOG(WARNING) << "Abort scan failed";
+  }
+  return Status::ok();
+}
+
 Status ScannerImpl::subscribeScanEvents(const sp<IScanEvent>& handler) {
+  if (!CheckIsValid()) {
+    return Status::ok();
+  }
+
   if (scan_event_handler_ != nullptr) {
     LOG(ERROR) << "Found existing scan events subscriber."
                << " This subscription request will unsubscribe it";
   }
   scan_event_handler_ = handler;
-  // Subscribe one-shot scan result notification.
-  scan_utils_->SubscribeScanResultNotification(
-      interface_index_,
-      std::bind(&ScannerImpl::OnScanResultsReady,
-                this,
-                _1, _2, _3, _4));
-
   return Status::ok();
 }
 
 Status ScannerImpl::unsubscribeScanEvents() {
-
-  scan_utils_->UnsubscribeScanResultNotification(interface_index_);
   scan_event_handler_ = nullptr;
   return Status::ok();
 }
 
 
 Status ScannerImpl::subscribePnoScanEvents(const sp<IPnoScanEvent>& handler) {
+  if (!CheckIsValid()) {
+    return Status::ok();
+  }
+
   if (pno_scan_event_handler_ != nullptr) {
     LOG(ERROR) << "Found existing pno scan events subscriber."
                << " This subscription request will unsubscribe it";
   }
   pno_scan_event_handler_ = handler;
 
-  // Subscribe scheduled scan result notification.
-  scan_utils_->SubscribeSchedScanResultNotification(
-      interface_index_,
-      std::bind(&ScannerImpl::OnSchedScanResultsReady,
-                this,
-                _1, _2));
-
   return Status::ok();
 }
 
 Status ScannerImpl::unsubscribePnoScanEvents() {
-  scan_utils_->UnsubscribeSchedScanResultNotification(interface_index_);
   pno_scan_event_handler_ = nullptr;
   return Status::ok();
 }
@@ -246,13 +340,20 @@ void ScannerImpl::OnScanResultsReady(
     bool aborted,
     vector<vector<uint8_t>>& ssids,
     vector<uint32_t>& frequencies) {
+  if (!scan_started_) {
+    LOG(INFO) << "Received external scan result notification from kernel.";
+  }
+  scan_started_ = false;
   if (scan_event_handler_ != nullptr) {
     // TODO: Pass other parameters back once we find framework needs them.
     if (aborted) {
+      LOG(WARNING) << "Scan aborted";
       scan_event_handler_->OnScanFailed();
     } else {
       scan_event_handler_->OnScanResultReady();
     }
+  } else {
+    LOG(WARNING) << "No scan event handler found.";
   }
 }
 
@@ -264,13 +365,31 @@ void ScannerImpl::OnSchedScanResultsReady(uint32_t interface_index,
       // This stop notification might result from our own request.
       // See the document for NL80211_CMD_SCHED_SCAN_STOPPED in nl80211.h.
       if (pno_scan_started_) {
+        LOG(WARNING) << "Unexpected pno scan stopped event";
         pno_scan_event_handler_->OnPnoScanFailed();
       }
+      pno_scan_started_ = false;
     } else {
+      LOG(INFO) << "Pno scan result ready event";
       pno_scan_event_handler_->OnPnoNetworkFound();
     }
   }
 }
 
+void ScannerImpl::LogSsidList(vector<vector<uint8_t>>& ssid_list,
+                              string prefix) {
+  if (ssid_list.empty()) {
+    return;
+  }
+  string ssid_list_string;
+  for (auto& ssid : ssid_list) {
+    ssid_list_string += string(ssid.begin(), ssid.end());
+    if (&ssid != &ssid_list.back()) {
+      ssid_list_string += ", ";
+    }
+  }
+  LOG(WARNING) << prefix << ": " << ssid_list_string;
+}
+
 }  // namespace wificond
 }  // namespace android