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