void MlmeEventHandlerImpl::OnConnect(unique_ptr<MlmeConnectEvent> event) {
if (event->GetStatusCode() == 0) {
+ client_interface_->is_associated_ = true;
client_interface_->RefreshAssociateFreq();
client_interface_->bssid_ = event->GetBSSID();
+ } else {
+ client_interface_->is_associated_ = false;
+ client_interface_->bssid_.clear();
}
}
void MlmeEventHandlerImpl::OnRoam(unique_ptr<MlmeRoamEvent> event) {
if (event->GetStatusCode() == 0) {
+ client_interface_->is_associated_ = true;
client_interface_->RefreshAssociateFreq();
client_interface_->bssid_ = event->GetBSSID();
+ } else {
+ client_interface_->is_associated_ = false;
+ client_interface_->bssid_.clear();
}
}
void MlmeEventHandlerImpl::OnAssociate(unique_ptr<MlmeAssociateEvent> event) {
if (event->GetStatusCode() == 0) {
+ client_interface_->is_associated_ = true;
client_interface_->RefreshAssociateFreq();
client_interface_->bssid_ = event->GetBSSID();
+ } else {
+ client_interface_->is_associated_ = false;
+ client_interface_->bssid_.clear();
}
}
+void MlmeEventHandlerImpl::OnDisconnect(unique_ptr<MlmeDisconnectEvent> event) {
+ client_interface_->is_associated_ = false;
+ client_interface_->bssid_.clear();
+}
+
+void MlmeEventHandlerImpl::OnDisassociate(unique_ptr<MlmeDisassociateEvent> event) {
+ client_interface_->is_associated_ = false;
+ client_interface_->bssid_.clear();
+}
+
+
ClientInterfaceImpl::ClientInterfaceImpl(
uint32_t wiphy_index,
const std::string& interface_name,
netlink_utils_(netlink_utils),
scan_utils_(scan_utils),
mlme_event_handler_(new MlmeEventHandlerImpl(this)),
- binder_(new ClientInterfaceBinder(this)) {
+ binder_(new ClientInterfaceBinder(this)),
+ is_associated_(false) {
netlink_utils_->SubscribeMlmeEvent(
interface_index_,
mlme_event_handler_.get());
interface_index_,
scan_capabilities_,
wiphy_features_,
+ this,
netlink_utils_,
scan_utils_);
}
return false;
}
+bool ClientInterfaceImpl::IsAssociated() {
+ return is_associated_;
+}
+
} // namespace wificond
} // namespace android
void OnConnect(std::unique_ptr<MlmeConnectEvent> event) override;
void OnRoam(std::unique_ptr<MlmeRoamEvent> event) override;
void OnAssociate(std::unique_ptr<MlmeAssociateEvent> event) override;
+ void OnDisconnect(std::unique_ptr<MlmeDisconnectEvent> event) override;
+ void OnDisassociate(std::unique_ptr<MlmeDisassociateEvent> event) override;
private:
ClientInterfaceImpl* client_interface_;
bool requestANQP(
const ::std::vector<uint8_t>& bssid,
const ::android::sp<::android::net::wifi::IANQPDoneCallback>& callback);
+ bool IsAssociated();
private:
bool RefreshAssociateFreq();
android::sp<ScannerImpl> scanner_;
// Cached information for this connection.
+ bool is_associated_;
std::vector<uint8_t> bssid_;
uint32_t associate_freq_;
LOG(ERROR) << "Failed to get NL80211_ATTR_IFINDEX";
return false;
}
+ // Some MLME events do not contain MAC address.
if (!packet->GetAttributeValue(NL80211_ATTR_MAC, bssid)) {
- LOG(ERROR) << "Failed to get NL80211_ATTR_MAC";
- return false;
+ LOG(DEBUG) << "Failed to get NL80211_ATTR_MAC";
}
return true;
}
return roam_event;
}
+unique_ptr<MlmeDisconnectEvent> MlmeDisconnectEvent::InitFromPacket(
+ const NL80211Packet* packet) {
+ if (packet->GetCommand() != NL80211_CMD_DISCONNECT) {
+ return nullptr;
+ }
+ unique_ptr<MlmeDisconnectEvent> disconnect_event(new MlmeDisconnectEvent());
+ if (!GetCommonFields(packet,
+ &(disconnect_event->interface_index_),
+ &(disconnect_event->bssid_))){
+ return nullptr;
+ }
+ return disconnect_event;
+}
+
+unique_ptr<MlmeDisassociateEvent> MlmeDisassociateEvent::InitFromPacket(
+ const NL80211Packet* packet) {
+ if (packet->GetCommand() != NL80211_CMD_DISASSOCIATE) {
+ return nullptr;
+ }
+ unique_ptr<MlmeDisassociateEvent> disassociate_event(new MlmeDisassociateEvent());
+ if (!GetCommonFields(packet,
+ &(disassociate_event->interface_index_),
+ &(disassociate_event->bssid_))){
+ return nullptr;
+ }
+ return disassociate_event;
+}
+
} // namespace wificond
} // namespace android
DISALLOW_COPY_AND_ASSIGN(MlmeRoamEvent);
};
+
+class MlmeDisconnectEvent {
+ public:
+ static std::unique_ptr<MlmeDisconnectEvent> InitFromPacket(
+ const NL80211Packet* packet);
+ uint32_t GetInterfaceIndex() const { return interface_index_; }
+ private:
+ MlmeDisconnectEvent() = default;
+
+ uint32_t interface_index_;
+ std::vector<uint8_t> bssid_;
+
+ DISALLOW_COPY_AND_ASSIGN(MlmeDisconnectEvent);
+};
+
+class MlmeDisassociateEvent {
+ public:
+ static std::unique_ptr<MlmeDisassociateEvent> InitFromPacket(
+ const NL80211Packet* packet);
+ uint32_t GetInterfaceIndex() const { return interface_index_; }
+ private:
+ MlmeDisassociateEvent() = default;
+
+ uint32_t interface_index_;
+ std::vector<uint8_t> bssid_;
+
+ DISALLOW_COPY_AND_ASSIGN(MlmeDisassociateEvent);
+};
+
} // namespace wificond
} // namespace android
virtual void OnConnect(std::unique_ptr<MlmeConnectEvent> event) = 0;
virtual void OnRoam(const std::unique_ptr<MlmeRoamEvent> event) = 0;
virtual void OnAssociate(std::unique_ptr<MlmeAssociateEvent> event) = 0;
+ virtual void OnDisconnect(std::unique_ptr<MlmeDisconnectEvent> event) = 0;
+ virtual void OnDisassociate(std::unique_ptr<MlmeDisassociateEvent> event) = 0;
};
// connection state better.
if (command == NL80211_CMD_CONNECT ||
command == NL80211_CMD_ASSOCIATE ||
- command == NL80211_CMD_ROAM) {
+ command == NL80211_CMD_ROAM ||
+ command == NL80211_CMD_DISCONNECT ||
+ command == NL80211_CMD_DISASSOCIATE) {
OnMlmeEvent(std::move(packet));
return;
}
if (command == NL80211_CMD_CONNECT) {
auto event = MlmeConnectEvent::InitFromPacket(packet.get());
if (event != nullptr) {
- handler->second->OnConnect(std::move(event));
+ handler->second->OnConnect(std::move(event));
}
return;
}
if (command == NL80211_CMD_ASSOCIATE) {
auto event = MlmeAssociateEvent::InitFromPacket(packet.get());
if (event != nullptr) {
- handler->second->OnAssociate(std::move(event));
+ handler->second->OnAssociate(std::move(event));
}
return;
}
if (command == NL80211_CMD_ROAM) {
auto event = MlmeRoamEvent::InitFromPacket(packet.get());
if (event != nullptr) {
- handler->second->OnRoam(std::move(event));
+ handler->second->OnRoam(std::move(event));
}
return;
}
+ if (command == NL80211_CMD_DISCONNECT) {
+ auto event = MlmeDisconnectEvent::InitFromPacket(packet.get());
+ if (event != nullptr) {
+ handler->second->OnDisconnect(std::move(event));
+ }
+ return;
+ }
+ if (command == NL80211_CMD_DISASSOCIATE) {
+ auto event = MlmeDisassociateEvent::InitFromPacket(packet.get());
+ if (event != nullptr) {
+ handler->second->OnDisassociate(std::move(event));
+ }
+ return;
+ }
+
}
void NetlinkManager::OnSchedScanResultsReady(unique_ptr<const NL80211Packet> packet) {
#include <android-base/logging.h>
+#include "wificond/client_interface_impl.h"
#include "wificond/scanning/scan_utils.h"
using android::binder::Status;
uint32_t interface_index,
const ScanCapabilities& scan_capabilities,
const WiphyFeatures& wiphy_features,
+ ClientInterfaceImpl* client_interface,
NetlinkUtils* netlink_utils,
ScanUtils* scan_utils)
: valid_(true),
interface_index_(interface_index),
scan_capabilities_(scan_capabilities),
wiphy_features_(wiphy_features),
+ client_interface_(client_interface),
netlink_utils_(netlink_utils),
scan_utils_(scan_utils),
scan_event_handler_(nullptr) {
if (scan_started_) {
LOG(WARNING) << "Scan already started";
}
- bool random_mac = wiphy_features_.supports_random_mac_oneshot_scan;
+ // Only request MAC address randomization when station is not associated.
+ bool request_random_mac = wiphy_features_.supports_random_mac_oneshot_scan &&
+ !client_interface_->IsAssociated();
// Initialize it with an empty ssid for a wild card scan.
vector<vector<uint8_t>> ssids = {{}};
freqs.push_back(channel.frequency_);
}
- if (!scan_utils_->Scan(interface_index_, random_mac, ssids, freqs)) {
+ if (!scan_utils_->Scan(interface_index_, request_random_mac, ssids, freqs)) {
*out_success = false;
return Status::ok();
}
match_ssids.push_back(network.ssid_);
}
- bool random_mac = wiphy_features_.supports_random_mac_sched_scan;
+ // Only request MAC address randomization when station is not associated.
+ bool request_random_mac = wiphy_features_.supports_random_mac_sched_scan &&
+ !client_interface_->IsAssociated();
if (!scan_utils_->StartScheduledScan(interface_index_,
pno_settings.interval_ms_,
// TODO: honor both rssi thresholds.
pno_settings.min_2g_rssi_,
- random_mac,
+ request_random_mac,
scan_ssids,
match_ssids,
freqs)) {
namespace android {
namespace wificond {
+class ClientInterfaceImpl;
class ScanUtils;
class ScannerImpl : public android::net::wifi::BnWifiScannerImpl {
uint32_t interface_index,
const ScanCapabilities& scan_capabilities,
const WiphyFeatures& wiphy_features,
+ ClientInterfaceImpl* client_interface,
NetlinkUtils* netlink_utils,
ScanUtils* scan_utils);
~ScannerImpl();
ScanCapabilities scan_capabilities_;
WiphyFeatures wiphy_features_;
+ ClientInterfaceImpl* client_interface_;
NetlinkUtils* const netlink_utils_;
ScanUtils* const scan_utils_;
::android::sp<::android::net::wifi::IPnoScanEvent> pno_scan_event_handler_;