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