// Remove this interface from wpa_supplicant's control.
// Returns true if removal was successful.
boolean disableSupplicant();
+
+ // Get packet counters for this interface.
+ // First element in array is the number of successfully transmitted packets.
+ // Second element in array is the number of tramsmission failure.
+ int[] getPacketCounters();
}
#include "wificond/client_interface_binder.h"
+#include <vector>
+
#include <binder/Status.h>
#include "wificond/client_interface_impl.h"
using android::binder::Status;
+using std::vector;
namespace android {
namespace wificond {
return Status::ok();
}
+Status ClientInterfaceBinder::getPacketCounters(
+ vector<int32_t>* out_packet_counters) {
+ if (impl_ == nullptr) {
+ return Status::ok();
+ }
+ impl_->GetPacketCounters(out_packet_counters);
+ return Status::ok();
+}
+
+
} // namespace wificond
} // namespace android
::android::binder::Status enableSupplicant(bool* success) override;
::android::binder::Status disableSupplicant(bool* success) override;
+ ::android::binder::Status getPacketCounters(
+ std::vector<int32_t>* out_packet_counters) override;
private:
ClientInterfaceImpl* impl_;
#include <wifi_system/wifi.h>
#include "wificond/client_interface_binder.h"
+#include "wificond/net/netlink_utils.h"
#include "wificond/scanning/scan_result.h"
#include "wificond/scanning/scan_utils.h"
using namespace std::placeholders;
using std::string;
+using std::unique_ptr;
using std::vector;
namespace android {
uint32_t interface_index,
const std::vector<uint8_t>& interface_mac_addr,
SupplicantManager* supplicant_manager,
+ NetlinkUtils* netlink_utils,
ScanUtils* scan_utils)
: interface_name_(interface_name),
interface_index_(interface_index),
interface_mac_addr_(interface_mac_addr),
supplicant_manager_(supplicant_manager),
+ netlink_utils_(netlink_utils),
scan_utils_(scan_utils),
binder_(new ClientInterfaceBinder(this)) {
scan_utils_->SubscribeScanResultNotification(
return supplicant_manager_->StopSupplicant();
}
+bool ClientInterfaceImpl::GetPacketCounters(vector<int32_t>* out_packet_counters) {
+ StationInfo station_info;
+ if(!netlink_utils_->GetStationInfo(interface_index_,
+ interface_mac_addr_,
+ &station_info)) {
+ return false;
+ }
+ out_packet_counters->push_back(station_info.station_tx_packets);
+ out_packet_counters->push_back(station_info.station_tx_failed);
+ return true;
+}
+
void ClientInterfaceImpl::OnScanResultsReady(
uint32_t interface_index,
std::vector<std::vector<uint8_t>>& ssids,
namespace wificond {
class ClientInterfaceBinder;
+class NetlinkUtils;
class ScanUtils;
// Holds the guts of how we control network interfaces capable of connecting to
uint32_t interface_index,
const std::vector<uint8_t>& interface_mac_addr,
android::wifi_system::SupplicantManager* supplicant_manager,
+ NetlinkUtils* netlink_utils,
ScanUtils* scan_utils);
~ClientInterfaceImpl();
bool EnableSupplicant();
bool DisableSupplicant();
+ bool GetPacketCounters(std::vector<int32_t>* out_packet_counters);
private:
void OnScanResultsReady(uint32_t interface_index,
const uint32_t interface_index_;
const std::vector<uint8_t> interface_mac_addr_;
android::wifi_system::SupplicantManager* const supplicant_manager_;
+ NetlinkUtils* const netlink_utils_;
ScanUtils* const scan_utils_;
const android::sp<ClientInterfaceBinder> binder_;
}
if (response->GetMessageType() == NLMSG_ERROR) {
LOG(ERROR) << "Receive ERROR message: "
- << strerror(response->GetErrorCode()) << "in response to a GetWiphy request";
+ << strerror(response->GetErrorCode())
+ << "in response to a GetWiphy request";
return false;
}
if (response->GetCommand() != NL80211_CMD_NEW_WIPHY) {
// Since there is no guarantee for the order of band attributes,
// we do some math here.
if (frequency_value > k2GHzFrequencyLowerBound &&
- frequency_value < k2GHzFrequencyUpperBound ) {
+ frequency_value < k2GHzFrequencyUpperBound) {
frequencies_2g.push_back(frequency_value);
} else {
frequencies_5g.push_back(frequency_value);
return true;
}
+bool NetlinkUtils::GetStationInfo(uint32_t interface_index,
+ const vector<uint8_t>& mac_address,
+ StationInfo* out_station_info) {
+ NL80211Packet get_station(
+ netlink_manager_->GetFamilyId(),
+ NL80211_CMD_GET_STATION,
+ netlink_manager_->GetSequenceNumber(),
+ getpid());
+ get_station.AddAttribute(NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX,
+ interface_index));
+ get_station.AddAttribute(NL80211Attr<vector<uint8_t>>(NL80211_ATTR_MAC,
+ mac_address));
+
+ unique_ptr<const NL80211Packet> response;
+ if (!netlink_manager_->SendMessageAndGetSingleResponse(get_station,
+ &response)) {
+ LOG(ERROR) << "Failed to get packet counters";
+ return false;
+ }
+ if (response->GetMessageType() == NLMSG_ERROR) {
+ LOG(ERROR) << "Receive ERROR message: "
+ << strerror(response->GetErrorCode())
+ << "in response to a get station request";
+ return false;
+ }
+
+ if (response->GetCommand() != NL80211_CMD_NEW_STATION) {
+ LOG(ERROR) << "Wrong command in response to a get station request: "
+ << static_cast<int>(response->GetCommand());
+ return false;
+ }
+ NL80211NestedAttr sta_info(0);
+ if (!response->GetAttribute(NL80211_ATTR_STA_INFO, &sta_info)) {
+ LOG(ERROR) << "Failed to get NL80211_ATTR_STA_INFO";
+ return false;
+ }
+ int32_t tx_good, tx_bad;
+ if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_PACKETS, &tx_good)) {
+ LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_PACKETS";
+ return false;
+ }
+ if (!sta_info.GetAttributeValue(NL80211_STA_INFO_TX_FAILED, &tx_bad)) {
+ LOG(ERROR) << "Failed to get NL80211_STA_INFO_TX_FAILED";
+ return false;
+ }
+ *out_station_info = StationInfo(tx_good, tx_bad);
+ return true;
+}
+
} // namespace wificond
} // namespace android
uint8_t max_match_sets;
};
+struct StationInfo {
+ StationInfo() = default;
+ StationInfo(uint32_t station_tx_packets_,
+ uint32_t station_tx_failed_)
+ : station_tx_packets(station_tx_packets_),
+ station_tx_failed(station_tx_failed_) {}
+ // Number of successfully transmitted packets.
+ int32_t station_tx_packets;
+ // number of tramsmission failures.
+ int32_t station_tx_failed;
+ // There are many other counters/parameters included in station info.
+ // We will add them once we find them useful.
+};
+
class NetlinkManager;
class NL80211Packet;
uint32_t* index,
std::vector<uint8_t>* mac_addr);
+ // Get wifi wiphy info from kernel.
+ // |*out_band_info| is the lists of frequencies in specific bands.
+ // |*out_scan_capabilities| is the lists of parameters specifying the
+ // scanning capability of underlying implementation.
+ // Returns true on success.
virtual bool GetWiphyInfo(uint32_t wiphy_index,
BandInfo* out_band_info,
ScanCapabilities* out_scan_capabilities);
+ // Get station info from kernel.
+ // |*out_station_info]| is the struct of available station information.
+ // Returns true on success.
+ virtual bool GetStationInfo(uint32_t interface_index,
+ const std::vector<uint8_t>& mac_address,
+ StationInfo* out_station_info);
+
private:
bool ParseBandInfo(const NL80211Packet* const packet,
BandInfo* out_band_info);
interface_index,
interface_mac_addr,
supplicant_manager_.get(),
+ netlink_utils_,
scan_utils_));
*created_interface = client_interface->GetBinder();
client_interfaces_.push_back(std::move(client_interface));
#include "wificond/client_interface_impl.h"
#include "wificond/tests/mock_netlink_manager.h"
+#include "wificond/tests/mock_netlink_utils.h"
#include "wificond/tests/mock_scan_utils.h"
using android::wifi_system::MockSupplicantManager;
kTestInterfaceIndex,
vector<uint8_t>{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
supplicant_manager_.get(),
+ &netlink_utils_,
&scan_utils_});
}
new NiceMock<MockSupplicantManager>};
unique_ptr<NiceMock<MockNetlinkManager>> netlink_manager_{
new NiceMock<MockNetlinkManager>()};
+ MockNetlinkUtils netlink_utils_{netlink_manager_.get()};
MockScanUtils scan_utils_{netlink_manager_.get()};
unique_ptr<ClientInterfaceImpl> client_interface_;
}; // class ClientInterfaceImplTest