ap_interface_impl.cpp \
client_interface_binder.cpp \
client_interface_impl.cpp \
+ logging_utils.cpp \
looper_backed_event_loop.cpp \
rtt/rtt_controller_binder.cpp \
rtt/rtt_controller_impl.cpp \
#include "wificond/net/netlink_utils.h"
#include "wificond/ap_interface_binder.h"
+#include "wificond/logging_utils.h"
using android::net::wifi::IApInterface;
using android::wifi_system::HostapdManager;
using EncryptionType = android::wifi_system::HostapdManager::EncryptionType;
+using namespace std::placeholders;
+
namespace android {
namespace wificond {
// This log keeps compiler happy.
LOG(DEBUG) << "Created ap interface " << interface_name_
<< " with index " << interface_index_;
+
+ netlink_utils_->SubscribeStationEvent(
+ interface_index_,
+ std::bind(&ApInterfaceImpl::OnStationEvent,
+ this,
+ _1, _2));
}
ApInterfaceImpl::~ApInterfaceImpl() {
binder_->NotifyImplDead();
if_tool_->SetUpState(interface_name_.c_str(), false);
+ netlink_utils_->UnsubscribeStationEvent(interface_index_);
}
sp<IApInterface> ApInterfaceImpl::GetBinder() const {
return hostapd_manager_->WriteHostapdConfig(config);
}
+void ApInterfaceImpl::OnStationEvent(StationEvent event,
+ const vector<uint8_t>& mac_address) {
+ if (event == NEW_STATION) {
+ LOG(INFO) << "New station "
+ << LoggingUtils::GetMacString(mac_address)
+ << " associated with hotspot";
+ } else if (event == DEL_STATION) {
+ LOG(INFO) << "Station "
+ << LoggingUtils::GetMacString(mac_address)
+ << " disassociated from hotspot";
+ }
+}
+
} // namespace wificond
} // namespace android
#include <wifi_system/hostapd_manager.h>
#include <wifi_system/interface_tool.h>
+#include "wificond/net/netlink_manager.h"
+
#include "android/net/wifi/IApInterface.h"
namespace android {
wifi_system::HostapdManager* const hostapd_manager_;
const android::sp<ApInterfaceBinder> binder_;
+ void OnStationEvent(StationEvent event,
+ const std::vector<uint8_t>& mac_address);
+
DISALLOW_COPY_AND_ASSIGN(ApInterfaceImpl);
};
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wificond/logging_utils.h"
+
+#include <iomanip>
+#include <vector>
+
+#include <android-base/macros.h>
+
+using std::string;
+using std::stringstream;
+using std::vector;
+
+namespace android {
+namespace wificond {
+
+string LoggingUtils::GetMacString(const vector<uint8_t>& mac_address) {
+ stringstream ss;
+ for (const uint8_t& b : mac_address) {
+ ss << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(b);
+ if (&b != &mac_address.back()) {
+ ss << ":";
+ }
+ }
+ return ss.str();
+}
+
+} // namespace wificond
+} // namespace android
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WIFICOND_LOGGING_UTILS_H_
+#define WIFICOND_LOGGING_UTILS_H_
+
+#include <vector>
+#include <sstream>
+
+#include <android-base/macros.h>
+
+namespace android {
+namespace wificond {
+
+class LoggingUtils {
+ public:
+ LoggingUtils() = default;
+ static std::string GetMacString(const std::vector<uint8_t>& mac_address);
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(LoggingUtils);
+};
+
+} // namespace wificond
+} // namespace android
+
+#endif // WIFICOND_LOGGING_UTILS_H_
OnRegChangeEvent(std::move(packet));
return;
}
+ // Station eventsFor AP mode.
+ if (command == NL80211_CMD_NEW_STATION ||
+ command == NL80211_CMD_DEL_STATION) {
+ uint32_t if_index;
+ if (!packet->GetAttributeValue(NL80211_ATTR_IFINDEX, &if_index)) {
+ LOG(WARNING) << "Failed to get interface index from station event";
+ return;
+ }
+ const auto handler = on_station_event_handler_.find(if_index);
+ if (handler != on_station_event_handler_.end()) {
+ vector<uint8_t> mac_address;
+ if (!packet->GetAttributeValue(NL80211_ATTR_MAC, &mac_address)) {
+ LOG(WARNING) << "Failed to get mac address from station event";
+ return;
+ }
+ if (command == NL80211_CMD_NEW_STATION) {
+ handler->second(NEW_STATION, mac_address);
+ } else {
+ handler->second(DEL_STATION, mac_address);
+ }
+ }
+ return;
+ }
}
void NetlinkManager::OnRegChangeEvent(unique_ptr<const NL80211Packet> packet) {
return;
}
- auto handler = on_reg_domain_changed_handler_.find(wiphy_index);
+ const auto handler = on_reg_domain_changed_handler_.find(wiphy_index);
if (handler == on_reg_domain_changed_handler_.end()) {
LOG(DEBUG) << "No handler for country code changed event from wiphy"
<< "with index: " << wiphy_index;
LOG(ERROR) << "Failed to get interface index from a MLME event message";
return;
}
- auto handler = on_mlme_event_handler_.find(if_index);
+ const auto handler = on_mlme_event_handler_.find(if_index);
if (handler == on_mlme_event_handler_.end()) {
LOG(DEBUG) << "No handler for mlme event from interface"
<< " with index: " << if_index;
return;
}
- auto handler = on_sched_scan_result_ready_handler_.find(if_index);
+ const auto handler = on_sched_scan_result_ready_handler_.find(if_index);
if (handler == on_sched_scan_result_ready_handler_.end()) {
LOG(DEBUG) << "No handler for scheduled scan result notification from"
<< " interface with index: " << if_index;
aborted = true;
}
- auto handler = on_scan_result_ready_handler_.find(if_index);
+ const auto handler = on_scan_result_ready_handler_.find(if_index);
if (handler == on_scan_result_ready_handler_.end()) {
LOG(WARNING) << "No handler for scan result notification from interface"
<< " with index: " << if_index;
handler->second(if_index, aborted, ssids, freqs);
}
+void NetlinkManager::SubscribeStationEvent(
+ uint32_t interface_index,
+ OnStationEventHandler handler) {
+ on_station_event_handler_[interface_index] = handler;
+}
+
+void NetlinkManager::UnsubscribeStationEvent(uint32_t interface_index) {
+ on_station_event_handler_.erase(interface_index);
+}
+
void NetlinkManager::SubscribeRegDomainChange(
uint32_t wiphy_index,
OnRegDomainChangedHandler handler) {
typedef std::function<void(
std::string& country_code)> OnRegDomainChangedHandler;
+// Enum used for identifying the type of a station event.
+// This is used by function |OnStationEventHandler|.
+enum StationEvent {
+ NEW_STATION,
+ DEL_STATION
+};
+
+// This describes a type of function handling station events.
+// |event| specifies the type of this event.
+// |mac_address| is the station mac address associated with this event.
+typedef std::function<void(
+ StationEvent event,
+ const std::vector<uint8_t>& mac_address)> OnStationEventHandler;
+
class NetlinkManager {
public:
explicit NetlinkManager(EventLoop* event_loop);
// from wiphy with index |wiphy_index|.
virtual void UnsubscribeRegDomainChange(uint32_t wiphy_index);
+ // Sign up to be notified when there is an station event.
+ // Only one handler can be registered per interface index.
+ // New handler will replace the registered handler if they are for the
+ // same interface index.
+ virtual void SubscribeStationEvent(uint32_t interface_index,
+ OnStationEventHandler handler);
+
+ // Cancel the sign-up of receiving station events.
+ virtual void UnsubscribeStationEvent(uint32_t interface_index);
+
private:
bool SetupSocket(android::base::unique_fd* netlink_fd);
bool WatchSocket(android::base::unique_fd* netlink_fd);
// regulatory domain change notifications.
std::map<uint32_t, OnRegDomainChangedHandler> on_reg_domain_changed_handler_;
+ std::map<uint32_t, OnStationEventHandler> on_station_event_handler_;
+
// Mapping from family name to family id, and group name to group id.
std::map<std::string, MessageType> message_types_;
netlink_manager_->UnsubscribeRegDomainChange(wiphy_index);
}
+void NetlinkUtils::SubscribeStationEvent(uint32_t interface_index,
+ OnStationEventHandler handler) {
+ netlink_manager_->SubscribeStationEvent(interface_index, handler);
+}
+
+void NetlinkUtils::UnsubscribeStationEvent(uint32_t interface_index) {
+ netlink_manager_->UnsubscribeStationEvent(interface_index);
+}
+
} // namespace wificond
} // namespace android
// from wiphy with index |wiphy_index|.
virtual void UnsubscribeRegDomainChange(uint32_t wiphy_index);
+ // Sign up to be notified when there is an station event.
+ // Only one handler can be registered per interface index.
+ // New handler will replace the registered handler if they are for the
+ // same interface index.
+ virtual void SubscribeStationEvent(uint32_t interface_index,
+ OnStationEventHandler handler);
+
+ // Cancel the sign-up of receiving station events.
+ virtual void UnsubscribeStationEvent(uint32_t interface_index);
+
private:
bool ParseBandInfo(const NL80211Packet* const packet,
BandInfo* out_band_info);
#include "wificond/scanning/scan_result.h"
-#include <iomanip>
-#include <sstream>
-
#include <android-base/logging.h>
+#include "wificond/logging_utils.h"
#include "wificond/parcelable_utils.h"
using android::status_t;
using android::OK;
using std::string;
-using std::stringstream;
namespace com {
namespace android {
string ssid_str(ssid.data(), ssid.data() + ssid.size());
LOG(INFO) << "SSID: " << ssid_str;
- stringstream ss;
- string bssid_str;
- for (uint8_t& b : bssid) {
- ss << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(b);
- if (&b != &bssid.back()) {
- ss << ":";
- }
- }
- bssid_str = ss.str();
- LOG(INFO) << "BSSID: " << bssid_str;
+ LOG(INFO) << "BSSID: "
+ << ::android::wificond::LoggingUtils::GetMacString(bssid);
LOG(INFO) << "FREQUENCY: " << frequency;
LOG(INFO) << "SIGNAL: " << signal_mbm/100 << "dBm";
LOG(INFO) << "TSF: " << tsf;
unique_ptr<NiceMock<MockNetlinkUtils>> netlink_utils_{
new NiceMock<MockNetlinkUtils>(netlink_manager_.get())};
- ApInterfaceImpl ap_interface_{kTestInterfaceName,
- kTestInterfaceIndex,
- netlink_utils_.get(),
- if_tool_.get(),
- hostapd_manager_.get()};
+ unique_ptr<ApInterfaceImpl> ap_interface_;
+
+ void SetUp() override {
+ EXPECT_CALL(*netlink_utils_,
+ SubscribeStationEvent(kTestInterfaceIndex, _));
+
+ ap_interface_.reset(new ApInterfaceImpl(
+ kTestInterfaceName,
+ kTestInterfaceIndex,
+ netlink_utils_.get(),
+ if_tool_.get(),
+ hostapd_manager_.get()));
+ }
}; // class ApInterfaceImplTest
} // namespace
TEST_F(ApInterfaceImplTest, ShouldReportStartFailure) {
EXPECT_CALL(*hostapd_manager_, StartHostapd())
.WillOnce(Return(false));
- EXPECT_FALSE(ap_interface_.StartHostapd());
+ EXPECT_FALSE(ap_interface_->StartHostapd());
}
TEST_F(ApInterfaceImplTest, ShouldReportStartSuccess) {
EXPECT_CALL(*hostapd_manager_, StartHostapd())
.WillOnce(Return(true));
- EXPECT_TRUE(ap_interface_.StartHostapd());
+ EXPECT_TRUE(ap_interface_->StartHostapd());
}
TEST_F(ApInterfaceImplTest, ShouldReportStopFailure) {
EXPECT_CALL(*hostapd_manager_, StopHostapd())
.WillOnce(Return(false));
- EXPECT_FALSE(ap_interface_.StopHostapd());
+ EXPECT_FALSE(ap_interface_->StopHostapd());
}
TEST_F(ApInterfaceImplTest, ShouldReportStopSuccess) {
EXPECT_CALL(*netlink_utils_, SetInterfaceMode(
kTestInterfaceIndex,
NetlinkUtils::STATION_MODE)).WillOnce(Return(true));
- EXPECT_TRUE(ap_interface_.StopHostapd());
+ EXPECT_TRUE(ap_interface_->StopHostapd());
testing::Mock::VerifyAndClearExpectations(if_tool_.get());
}
EXPECT_CALL(*hostapd_manager_, CreateHostapdConfig(_, _, _, _, _, _))
.WillOnce(Return(""));
EXPECT_CALL(*hostapd_manager_, WriteHostapdConfig(_)).Times(0);
- EXPECT_FALSE(ap_interface_.WriteHostapdConfig(
+ EXPECT_FALSE(ap_interface_->WriteHostapdConfig(
vector<uint8_t>(),
false,
0,
MOCK_METHOD1(GetWiphyIndex, bool(uint32_t* out_wiphy_index));
MOCK_METHOD1(UnsubscribeMlmeEvent, void(uint32_t interface_index));
MOCK_METHOD1(UnsubscribeRegDomainChange, void(uint32_t wiphy_index));
+ MOCK_METHOD1(UnsubscribeStationEvent, void(uint32_t interface_index));
MOCK_METHOD2(SetInterfaceMode,
bool(uint32_t interface_index, InterfaceMode mode));
MOCK_METHOD2(SubscribeMlmeEvent,
MOCK_METHOD2(SubscribeRegDomainChange,
void(uint32_t wiphy_index,
OnRegDomainChangedHandler handler));
+ MOCK_METHOD2(SubscribeStationEvent,
+ void(uint32_t interface_index,
+ OnStationEventHandler handler));
MOCK_METHOD2(GetInterfaces,
bool(uint32_t wiphy_index,