#include <android-base/logging.h>
+#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 android::wifi_system::InterfaceTool;
+using std::endl;
using std::string;
using std::unique_ptr;
using std::vector;
using EncryptionType = android::wifi_system::HostapdManager::EncryptionType;
+using namespace std::placeholders;
+
namespace android {
namespace wificond {
ApInterfaceImpl::ApInterfaceImpl(const string& interface_name,
uint32_t interface_index,
- unique_ptr<HostapdManager> hostapd_manager)
+ NetlinkUtils* netlink_utils,
+ InterfaceTool* if_tool,
+ HostapdManager* hostapd_manager)
: interface_name_(interface_name),
interface_index_(interface_index),
- hostapd_manager_(std::move(hostapd_manager)),
- binder_(new ApInterfaceBinder(this)) {
+ netlink_utils_(netlink_utils),
+ if_tool_(if_tool),
+ hostapd_manager_(hostapd_manager),
+ binder_(new ApInterfaceBinder(this)),
+ number_of_associated_stations_(0) {
// 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 binder_;
}
+void ApInterfaceImpl::Dump(std::stringstream* ss) const {
+ *ss << "------- Dump of AP interface with index: "
+ << interface_index_ << " and name: " << interface_name_
+ << "-------" << endl;
+ *ss << "Number of associated stations: "
+ << number_of_associated_stations_ << endl;
+ *ss << "------- Dump End -------" << endl;
+}
+
bool ApInterfaceImpl::StartHostapd() {
return hostapd_manager_->StartHostapd();
}
bool ApInterfaceImpl::StopHostapd() {
- pid_t hostapd_pid;
- if (hostapd_manager_->GetHostapdPid(&hostapd_pid)) {
- // We do this because it was found that hostapd would leave the driver in a
- // bad state if init killed it harshly with a SIGKILL. b/30311493
- if (kill(hostapd_pid, SIGTERM) == -1) {
- LOG(ERROR) << "Error delivering signal to hostapd: " << strerror(errno);
- }
- // This should really be asynchronous: b/30465379
- for (int tries = 0; tries < 10; tries++) {
- // Try to give hostapd some time to go down.
- if (!hostapd_manager_->IsHostapdRunning()) {
- break;
- }
- usleep(10 * 1000); // Don't busy wait.
- }
+ // Drop SIGKILL on hostapd.
+ if (!hostapd_manager_->StopHostapd()) {
+ // Logging was done internally.
+ return false;
+ }
+
+ // Take down the interface.
+ if (!if_tool_->SetUpState(interface_name_.c_str(), false)) {
+ // Logging was done internally.
+ return false;
}
- // Always drop a SIGKILL on hostapd on the way out, just in case.
- return hostapd_manager_->StopHostapd();
+ // Since wificond SIGKILLs hostapd, hostapd has no chance to handle
+ // the cleanup.
+ // Besides taking down the interface, we also need to set the interface mode
+ // back to station mode for the cleanup.
+ if (!netlink_utils_->SetInterfaceMode(interface_index_,
+ NetlinkUtils::STATION_MODE)) {
+ LOG(ERROR) << "Failed to set interface back to station mode";
+ return false;
+ }
+
+ return true;
}
bool ApInterfaceImpl::WriteHostapdConfig(const vector<uint8_t>& ssid,
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";
+ number_of_associated_stations_++;
+ } else if (event == DEL_STATION) {
+ LOG(INFO) << "Station "
+ << LoggingUtils::GetMacString(mac_address)
+ << " disassociated from hotspot";
+ if (number_of_associated_stations_ <= 0) {
+ LOG(ERROR) << "Received DEL_STATION event when station counter is: "
+ << number_of_associated_stations_;
+ } else {
+ number_of_associated_stations_--;
+ }
+ }
+}
+
+int ApInterfaceImpl::GetNumberOfAssociatedStations() const {
+ return number_of_associated_stations_;
+}
+
} // namespace wificond
} // namespace android