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