• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <utils/Timers.h>
23 
24 #include "wificond/client_interface_binder.h"
25 #include "wificond/logging_utils.h"
26 #include "wificond/net/mlme_event.h"
27 #include "wificond/net/netlink_utils.h"
28 #include "wificond/scanning/offload/offload_service_utils.h"
29 #include "wificond/scanning/scan_result.h"
30 #include "wificond/scanning/scan_utils.h"
31 #include "wificond/scanning/scanner_impl.h"
32 
33 using android::net::wifi::IClientInterface;
34 using android::net::wifi::ISendMgmtFrameEvent;
35 using com::android::server::wifi::wificond::NativeScanResult;
36 using android::sp;
37 using android::wifi_system::InterfaceTool;
38 
39 using std::endl;
40 using std::string;
41 using std::unique_ptr;
42 using std::vector;
43 
44 namespace android {
45 namespace wificond {
46 
MlmeEventHandlerImpl(ClientInterfaceImpl * client_interface)47 MlmeEventHandlerImpl::MlmeEventHandlerImpl(ClientInterfaceImpl* client_interface)
48     : client_interface_(client_interface) {
49 }
50 
~MlmeEventHandlerImpl()51 MlmeEventHandlerImpl::~MlmeEventHandlerImpl() {
52 }
53 
OnConnect(unique_ptr<MlmeConnectEvent> event)54 void MlmeEventHandlerImpl::OnConnect(unique_ptr<MlmeConnectEvent> event) {
55   if (!event->IsTimeout() && event->GetStatusCode() == 0) {
56     client_interface_->is_associated_ = true;
57     client_interface_->RefreshAssociateFreq();
58     client_interface_->bssid_ = event->GetBSSID();
59   } else {
60     if (event->IsTimeout()) {
61       LOG(INFO) << "Connect timeout";
62     }
63     client_interface_->is_associated_ = false;
64     client_interface_->bssid_.fill(0);
65   }
66 }
67 
OnRoam(unique_ptr<MlmeRoamEvent> event)68 void MlmeEventHandlerImpl::OnRoam(unique_ptr<MlmeRoamEvent> event) {
69   client_interface_->is_associated_ = true;
70   client_interface_->RefreshAssociateFreq();
71   client_interface_->bssid_ = event->GetBSSID();
72 }
73 
OnAssociate(unique_ptr<MlmeAssociateEvent> event)74 void MlmeEventHandlerImpl::OnAssociate(unique_ptr<MlmeAssociateEvent> event) {
75   if (!event->IsTimeout() && event->GetStatusCode() == 0) {
76     client_interface_->is_associated_ = true;
77     client_interface_->RefreshAssociateFreq();
78     client_interface_->bssid_ = event->GetBSSID();
79   } else {
80     if (event->IsTimeout()) {
81       LOG(INFO) << "Associate timeout";
82     }
83     client_interface_->is_associated_ = false;
84     client_interface_->bssid_.fill(0);
85   }
86 }
87 
OnDisconnect(unique_ptr<MlmeDisconnectEvent> event)88 void MlmeEventHandlerImpl::OnDisconnect(unique_ptr<MlmeDisconnectEvent> event) {
89   client_interface_->is_associated_ = false;
90   client_interface_->bssid_.fill(0);
91 }
92 
OnDisassociate(unique_ptr<MlmeDisassociateEvent> event)93 void MlmeEventHandlerImpl::OnDisassociate(unique_ptr<MlmeDisassociateEvent> event) {
94   client_interface_->is_associated_ = false;
95   client_interface_->bssid_.fill(0);
96 }
97 
98 
ClientInterfaceImpl(uint32_t wiphy_index,const std::string & interface_name,uint32_t interface_index,const std::array<uint8_t,ETH_ALEN> & interface_mac_addr,InterfaceTool * if_tool,NetlinkUtils * netlink_utils,ScanUtils * scan_utils)99 ClientInterfaceImpl::ClientInterfaceImpl(
100     uint32_t wiphy_index,
101     const std::string& interface_name,
102     uint32_t interface_index,
103     const std::array<uint8_t, ETH_ALEN>& interface_mac_addr,
104     InterfaceTool* if_tool,
105     NetlinkUtils* netlink_utils,
106     ScanUtils* scan_utils)
107     : wiphy_index_(wiphy_index),
108       interface_name_(interface_name),
109       interface_index_(interface_index),
110       interface_mac_addr_(interface_mac_addr),
111       if_tool_(if_tool),
112       netlink_utils_(netlink_utils),
113       scan_utils_(scan_utils),
114       offload_service_utils_(new OffloadServiceUtils()),
115       mlme_event_handler_(new MlmeEventHandlerImpl(this)),
116       binder_(new ClientInterfaceBinder(this)),
117       is_associated_(false),
118       frame_tx_in_progress_(false),
119       frame_tx_status_cookie_(0),
120       on_frame_tx_status_event_handler_([](bool was_acked) {}) {
121   netlink_utils_->SubscribeMlmeEvent(
122       interface_index_,
123       mlme_event_handler_.get());
124 
125   netlink_utils_->SubscribeFrameTxStatusEvent(
126       interface_index,
__anon98a6401d0202(uint64_t cookie, bool was_acked) 127       [this](uint64_t cookie, bool was_acked) {
128         if (frame_tx_in_progress_ && frame_tx_status_cookie_ == cookie) {
129           on_frame_tx_status_event_handler_(was_acked);
130           frame_tx_in_progress_ = false;
131           frame_tx_status_cookie_ = 0;
132           on_frame_tx_status_event_handler_ = [](bool was_acked) {};
133         }
134       });
135 
136   if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
137                                &band_info_,
138                                &scan_capabilities_,
139                                &wiphy_features_)) {
140     LOG(ERROR) << "Failed to get wiphy info from kernel";
141   }
142   LOG(INFO) << "create scanner for interface with index: "
143             << (int)interface_index_;
144   scanner_ = new ScannerImpl(interface_index_,
145                              scan_capabilities_,
146                              wiphy_features_,
147                              this,
148                              scan_utils_,
149                              offload_service_utils_);
150   // Need to set the interface up (especially in scan mode since wpa_supplicant
151   // is not started)
152   if_tool_->SetUpState(interface_name_.c_str(), true);
153 }
154 
~ClientInterfaceImpl()155 ClientInterfaceImpl::~ClientInterfaceImpl() {
156   binder_->NotifyImplDead();
157   scanner_->Invalidate();
158   netlink_utils_->UnsubscribeFrameTxStatusEvent(interface_index_);
159   netlink_utils_->UnsubscribeMlmeEvent(interface_index_);
160   if_tool_->SetUpState(interface_name_.c_str(), false);
161 }
162 
GetBinder() const163 sp<android::net::wifi::IClientInterface> ClientInterfaceImpl::GetBinder() const {
164   return binder_;
165 }
166 
Dump(std::stringstream * ss) const167 void ClientInterfaceImpl::Dump(std::stringstream* ss) const {
168   *ss << "------- Dump of client interface with index: "
169       << interface_index_ << " and name: " << interface_name_
170       << "-------" << endl;
171   *ss << "Max number of ssids for single shot scan: "
172       << static_cast<int>(scan_capabilities_.max_num_scan_ssids) << endl;
173   *ss << "Max number of ssids for scheduled scan: "
174       << static_cast<int>(scan_capabilities_.max_num_sched_scan_ssids) << endl;
175   *ss << "Max number of match sets for scheduled scan: "
176       << static_cast<int>(scan_capabilities_.max_match_sets) << endl;
177   *ss << "Maximum number of scan plans: "
178       << scan_capabilities_.max_num_scan_plans << endl;
179   *ss << "Max scan plan interval in seconds: "
180       << scan_capabilities_.max_scan_plan_interval << endl;
181   *ss << "Max scan plan iterations: "
182       << scan_capabilities_.max_scan_plan_iterations << endl;
183   *ss << "Device supports random MAC for single shot scan: "
184       << wiphy_features_.supports_random_mac_oneshot_scan << endl;
185   *ss << "Device supports low span single shot scan: "
186       << wiphy_features_.supports_low_span_oneshot_scan << endl;
187   *ss << "Device supports low power single shot scan: "
188       << wiphy_features_.supports_low_power_oneshot_scan << endl;
189   *ss << "Device supports high accuracy single shot scan: "
190       << wiphy_features_.supports_high_accuracy_oneshot_scan << endl;
191   *ss << "Device supports random MAC for scheduled scan: "
192       << wiphy_features_.supports_random_mac_sched_scan << endl;
193   *ss << "Device supports sending management frames at specified MCS rate: "
194       << wiphy_features_.supports_tx_mgmt_frame_mcs << endl;
195   *ss << "------- Dump End -------" << endl;
196 }
197 
GetPacketCounters(vector<int32_t> * out_packet_counters)198 bool ClientInterfaceImpl::GetPacketCounters(vector<int32_t>* out_packet_counters) {
199   StationInfo station_info;
200   if (!netlink_utils_->GetStationInfo(interface_index_,
201                                       bssid_,
202                                       &station_info)) {
203     return false;
204   }
205   out_packet_counters->push_back(station_info.station_tx_packets);
206   out_packet_counters->push_back(station_info.station_tx_failed);
207 
208   return true;
209 }
210 
SignalPoll(vector<int32_t> * out_signal_poll_results)211 bool ClientInterfaceImpl::SignalPoll(vector<int32_t>* out_signal_poll_results) {
212   if (!IsAssociated()) {
213     LOG(INFO) << "Fail RSSI polling because wifi is not associated.";
214     return false;
215   }
216 
217   StationInfo station_info;
218   if (!netlink_utils_->GetStationInfo(interface_index_,
219                                       bssid_,
220                                       &station_info)) {
221     return false;
222   }
223   out_signal_poll_results->push_back(
224       static_cast<int32_t>(station_info.current_rssi));
225   // Convert from 100kbit/s to Mbps.
226   out_signal_poll_results->push_back(
227       static_cast<int32_t>(station_info.station_tx_bitrate/10));
228   // Association frequency.
229   out_signal_poll_results->push_back(
230       static_cast<int32_t>(associate_freq_));
231   // Convert from 100kbit/s to Mbps.
232   out_signal_poll_results->push_back(
233       static_cast<int32_t>(station_info.station_rx_bitrate/10));
234 
235   return true;
236 }
237 
GetMacAddress()238 const std::array<uint8_t, ETH_ALEN>& ClientInterfaceImpl::GetMacAddress() {
239   return interface_mac_addr_;
240 }
241 
SetMacAddress(const std::array<uint8_t,ETH_ALEN> & mac)242 bool ClientInterfaceImpl::SetMacAddress(const std::array<uint8_t, ETH_ALEN>& mac) {
243   if (!if_tool_->SetWifiUpState(false)) {
244     LOG(ERROR) << "SetWifiUpState(false) failed.";
245     return false;
246   }
247   if (!if_tool_->SetMacAddress(interface_name_.c_str(), mac)) {
248     LOG(ERROR) << "SetMacAddress(" << interface_name_ << ", "
249                << LoggingUtils::GetMacString(mac) << ") failed.";
250     return false;
251   }
252   if (!if_tool_->SetWifiUpState(true)) {
253     LOG(ERROR) << "SetWifiUpState(true) failed.";
254     return false;
255   }
256   LOG(DEBUG) << "Successfully SetMacAddress.";
257   return true;
258 }
259 
RefreshAssociateFreq()260 bool ClientInterfaceImpl::RefreshAssociateFreq() {
261   // wpa_supplicant fetches associate frequency using the latest scan result.
262   // We should follow the same method here before we find a better solution.
263   std::vector<NativeScanResult> scan_results;
264   if (!scan_utils_->GetScanResult(interface_index_, &scan_results)) {
265     return false;
266   }
267   for (auto& scan_result : scan_results) {
268     if (scan_result.associated) {
269       associate_freq_ = scan_result.frequency;
270     }
271   }
272   return false;
273 }
274 
IsAssociated() const275 bool ClientInterfaceImpl::IsAssociated() const {
276   return is_associated_;
277 }
278 
SendMgmtFrame(const vector<uint8_t> & frame,const sp<ISendMgmtFrameEvent> & callback,int32_t mcs)279 void ClientInterfaceImpl::SendMgmtFrame(const vector<uint8_t>& frame,
280     const sp<ISendMgmtFrameEvent>& callback, int32_t mcs) {
281   if (mcs >= 0 && !wiphy_features_.supports_tx_mgmt_frame_mcs) {
282     callback->OnFailure(
283         ISendMgmtFrameEvent::SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED);
284     return;
285   }
286 
287   uint64_t cookie;
288   if (!netlink_utils_->SendMgmtFrame(interface_index_, frame, mcs, &cookie)) {
289     callback->OnFailure(ISendMgmtFrameEvent::SEND_MGMT_FRAME_ERROR_UNKNOWN);
290     return;
291   }
292 
293   frame_tx_in_progress_ = true;
294   frame_tx_status_cookie_ = cookie;
295   nsecs_t start_time_ns = systemTime(SYSTEM_TIME_MONOTONIC);
296   on_frame_tx_status_event_handler_ =
297       [callback, start_time_ns](bool was_acked) {
298         if (was_acked) {
299           nsecs_t end_time_ns = systemTime(SYSTEM_TIME_MONOTONIC);
300           int32_t elapsed_time_ms = static_cast<int32_t>(
301               nanoseconds_to_milliseconds(end_time_ns - start_time_ns));
302           callback->OnAck(elapsed_time_ms);
303         } else {
304           callback->OnFailure(
305               ISendMgmtFrameEvent::SEND_MGMT_FRAME_ERROR_NO_ACK);
306         }
307       };
308 }
309 
310 }  // namespace wificond
311 }  // namespace android
312