Home | History | Annotate | Download | only in wificond
      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/client_interface_impl.h"
     18 
     19 #include <vector>
     20 
     21 #include <android-base/logging.h>
     22 #include <wifi_system/supplicant_manager.h>
     23 
     24 #include "wificond/client_interface_binder.h"
     25 #include "wificond/net/mlme_event.h"
     26 #include "wificond/net/netlink_utils.h"
     27 #include "wificond/scanning/offload/offload_service_utils.h"
     28 #include "wificond/scanning/scan_result.h"
     29 #include "wificond/scanning/scan_utils.h"
     30 #include "wificond/scanning/scanner_impl.h"
     31 
     32 using android::net::wifi::IClientInterface;
     33 using com::android::server::wifi::wificond::NativeScanResult;
     34 using android::sp;
     35 using android::wifi_system::InterfaceTool;
     36 using android::wifi_system::SupplicantManager;
     37 
     38 using std::endl;
     39 using std::string;
     40 using std::unique_ptr;
     41 using std::vector;
     42 
     43 namespace android {
     44 namespace wificond {
     45 
     46 MlmeEventHandlerImpl::MlmeEventHandlerImpl(ClientInterfaceImpl* client_interface)
     47     : client_interface_(client_interface) {
     48 }
     49 
     50 MlmeEventHandlerImpl::~MlmeEventHandlerImpl() {
     51 }
     52 
     53 void MlmeEventHandlerImpl::OnConnect(unique_ptr<MlmeConnectEvent> event) {
     54   if (!event->IsTimeout() && event->GetStatusCode() == 0) {
     55     client_interface_->is_associated_ = true;
     56     client_interface_->RefreshAssociateFreq();
     57     client_interface_->bssid_ = event->GetBSSID();
     58   } else {
     59     if (event->IsTimeout()) {
     60       LOG(INFO) << "Connect timeout";
     61     }
     62     client_interface_->is_associated_ = false;
     63     client_interface_->bssid_.clear();
     64   }
     65 }
     66 
     67 void MlmeEventHandlerImpl::OnRoam(unique_ptr<MlmeRoamEvent> event) {
     68   if (event->GetStatusCode() == 0) {
     69     client_interface_->is_associated_ = true;
     70     client_interface_->RefreshAssociateFreq();
     71     client_interface_->bssid_ = event->GetBSSID();
     72   } else {
     73     client_interface_->is_associated_ = false;
     74     client_interface_->bssid_.clear();
     75   }
     76 }
     77 
     78 void MlmeEventHandlerImpl::OnAssociate(unique_ptr<MlmeAssociateEvent> event) {
     79   if (!event->IsTimeout() && event->GetStatusCode() == 0) {
     80     client_interface_->is_associated_ = true;
     81     client_interface_->RefreshAssociateFreq();
     82     client_interface_->bssid_ = event->GetBSSID();
     83   } else {
     84     if (event->IsTimeout()) {
     85       LOG(INFO) << "Associate timeout";
     86     }
     87     client_interface_->is_associated_ = false;
     88     client_interface_->bssid_.clear();
     89   }
     90 }
     91 
     92 void MlmeEventHandlerImpl::OnDisconnect(unique_ptr<MlmeDisconnectEvent> event) {
     93   client_interface_->is_associated_ = false;
     94   client_interface_->bssid_.clear();
     95 }
     96 
     97 void MlmeEventHandlerImpl::OnDisassociate(unique_ptr<MlmeDisassociateEvent> event) {
     98   client_interface_->is_associated_ = false;
     99   client_interface_->bssid_.clear();
    100 }
    101 
    102 
    103 ClientInterfaceImpl::ClientInterfaceImpl(
    104     uint32_t wiphy_index,
    105     const std::string& interface_name,
    106     uint32_t interface_index,
    107     const std::vector<uint8_t>& interface_mac_addr,
    108     InterfaceTool* if_tool,
    109     SupplicantManager* supplicant_manager,
    110     NetlinkUtils* netlink_utils,
    111     ScanUtils* scan_utils)
    112     : wiphy_index_(wiphy_index),
    113       interface_name_(interface_name),
    114       interface_index_(interface_index),
    115       interface_mac_addr_(interface_mac_addr),
    116       if_tool_(if_tool),
    117       supplicant_manager_(supplicant_manager),
    118       netlink_utils_(netlink_utils),
    119       scan_utils_(scan_utils),
    120       offload_service_utils_(new OffloadServiceUtils()),
    121       mlme_event_handler_(new MlmeEventHandlerImpl(this)),
    122       binder_(new ClientInterfaceBinder(this)),
    123       is_associated_(false) {
    124   netlink_utils_->SubscribeMlmeEvent(
    125       interface_index_,
    126       mlme_event_handler_.get());
    127   if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
    128                                &band_info_,
    129                                &scan_capabilities_,
    130                                &wiphy_features_)) {
    131     LOG(ERROR) << "Failed to get wiphy info from kernel";
    132   }
    133   LOG(INFO) << "create scanner for interface with index: "
    134             << (int)interface_index_;
    135   scanner_ = new ScannerImpl(wiphy_index,
    136                              interface_index_,
    137                              scan_capabilities_,
    138                              wiphy_features_,
    139                              this,
    140                              netlink_utils_,
    141                              scan_utils_,
    142                              offload_service_utils_);
    143 }
    144 
    145 ClientInterfaceImpl::~ClientInterfaceImpl() {
    146   binder_->NotifyImplDead();
    147   scanner_->Invalidate();
    148   DisableSupplicant();
    149   netlink_utils_->UnsubscribeMlmeEvent(interface_index_);
    150   if_tool_->SetUpState(interface_name_.c_str(), false);
    151 }
    152 
    153 sp<android::net::wifi::IClientInterface> ClientInterfaceImpl::GetBinder() const {
    154   return binder_;
    155 }
    156 
    157 void ClientInterfaceImpl::Dump(std::stringstream* ss) const {
    158   *ss << "------- Dump of client interface with index: "
    159       << interface_index_ << " and name: " << interface_name_
    160       << "-------" << endl;
    161   *ss << "Max number of ssids for single shot scan: "
    162       << static_cast<int>(scan_capabilities_.max_num_scan_ssids) << endl;
    163   *ss << "Max number of ssids for scheduled scan: "
    164       << static_cast<int>(scan_capabilities_.max_num_sched_scan_ssids) << endl;
    165   *ss << "Max number of match sets for scheduled scan: "
    166       << static_cast<int>(scan_capabilities_.max_match_sets) << endl;
    167   *ss << "Maximum number of scan plans: "
    168       << scan_capabilities_.max_num_scan_plans << endl;
    169   *ss << "Max scan plan interval in seconds: "
    170       << scan_capabilities_.max_scan_plan_interval << endl;
    171   *ss << "Max scan plan iterations: "
    172       << scan_capabilities_.max_scan_plan_iterations << endl;
    173   *ss << "Device supports random MAC for single shot scan: "
    174       << wiphy_features_.supports_random_mac_oneshot_scan << endl;
    175   *ss << "Device supports random MAC for scheduled scan: "
    176       << wiphy_features_.supports_random_mac_sched_scan << endl;
    177   *ss << "------- Dump End -------" << endl;
    178 }
    179 
    180 bool ClientInterfaceImpl::EnableSupplicant() {
    181   return supplicant_manager_->StartSupplicant();
    182 }
    183 
    184 bool ClientInterfaceImpl::DisableSupplicant() {
    185   return supplicant_manager_->StopSupplicant();
    186 }
    187 
    188 bool ClientInterfaceImpl::GetPacketCounters(vector<int32_t>* out_packet_counters) {
    189   StationInfo station_info;
    190   if (!netlink_utils_->GetStationInfo(interface_index_,
    191                                       bssid_,
    192                                       &station_info)) {
    193     return false;
    194   }
    195   out_packet_counters->push_back(station_info.station_tx_packets);
    196   out_packet_counters->push_back(station_info.station_tx_failed);
    197 
    198   return true;
    199 }
    200 
    201 bool ClientInterfaceImpl::SignalPoll(vector<int32_t>* out_signal_poll_results) {
    202   if (!IsAssociated()) {
    203     LOG(INFO) << "Fail RSSI polling because wifi is not associated.";
    204     return false;
    205   }
    206 
    207   StationInfo station_info;
    208   if (!netlink_utils_->GetStationInfo(interface_index_,
    209                                       bssid_,
    210                                       &station_info)) {
    211     return false;
    212   }
    213   out_signal_poll_results->push_back(
    214       static_cast<int32_t>(station_info.current_rssi));
    215   // Convert from 100kbit/s to Mbps.
    216   out_signal_poll_results->push_back(
    217       static_cast<int32_t>(station_info.station_tx_bitrate/10));
    218   // Association frequency.
    219   out_signal_poll_results->push_back(
    220       static_cast<int32_t>(associate_freq_));
    221 
    222   return true;
    223 }
    224 
    225 const vector<uint8_t>& ClientInterfaceImpl::GetMacAddress() {
    226   return interface_mac_addr_;
    227 }
    228 
    229 bool ClientInterfaceImpl::requestANQP(
    230       const ::std::vector<uint8_t>& bssid,
    231       const ::android::sp<::android::net::wifi::IANQPDoneCallback>& callback) {
    232   // TODO(nywang): query ANQP information from wpa_supplicant.
    233   return true;
    234 }
    235 
    236 bool ClientInterfaceImpl::RefreshAssociateFreq() {
    237   // wpa_supplicant fetches associate frequency using the latest scan result.
    238   // We should follow the same method here before we find a better solution.
    239   std::vector<NativeScanResult> scan_results;
    240   if (!scan_utils_->GetScanResult(interface_index_, &scan_results)) {
    241     return false;
    242   }
    243   for (auto& scan_result : scan_results) {
    244     if (scan_result.associated) {
    245       associate_freq_ = scan_result.frequency;
    246     }
    247   }
    248   return false;
    249 }
    250 
    251 bool ClientInterfaceImpl::IsAssociated() const {
    252   return is_associated_;
    253 }
    254 
    255 }  // namespace wificond
    256 }  // namespace android
    257