Use additional interface for the WiFi Aware Discovery operations.

NAN operations are currently done on the STA interface.This resulted
in the NAN sessions getting terminated in all the instances where the
STA interface is restarted (IFF DOWN/UP), due to connected MAC
randomization.
Hence, remove the dependency of NAN over STA interface. This change
expects the driver to create a dedicated interface for the
NAN operations. The iface name needs to be set in "wifi.aware.interface"
property.

Bug: 1636219
Test: HAL unit tests
Test: Device boots up and connects to wifi network.
Change-Id: I1b6d64eb94334172a8cd621d0b15ed8c8dc87f91
This commit is contained in:
Roshan Pius 2020-04-14 11:55:42 -07:00
parent 432974a63e
commit 5ba0a90cac
11 changed files with 82 additions and 15 deletions

View file

@ -156,6 +156,11 @@ LOCAL_SRC_FILES := \
LOCAL_STATIC_LIBRARIES := \
libgmock \
libgtest \
android.hardware.wifi@1.0 \
android.hardware.wifi@1.1 \
android.hardware.wifi@1.2 \
android.hardware.wifi@1.3 \
android.hardware.wifi@1.4 \
android.hardware.wifi@1.0-service-lib
LOCAL_SHARED_LIBRARIES := \
libbase \
@ -165,10 +170,5 @@ LOCAL_SHARED_LIBRARIES := \
libnl \
libutils \
libwifi-hal \
libwifi-system-iface \
android.hardware.wifi@1.0 \
android.hardware.wifi@1.1 \
android.hardware.wifi@1.2 \
android.hardware.wifi@1.3 \
android.hardware.wifi@1.4
libwifi-system-iface
include $(BUILD_NATIVE_TEST)

View file

@ -40,6 +40,7 @@ class MockWifiIfaceUtil : public WifiIfaceUtil {
MOCK_METHOD2(registerIfaceEventHandlers,
void(const std::string&, IfaceEventHandlers));
MOCK_METHOD1(unregisterIfaceEventHandlers, void(const std::string&));
MOCK_METHOD2(setUpState, bool(const std::string&, bool));
};
} // namespace iface_util
} // namespace implementation

View file

@ -57,6 +57,10 @@ class MockWifiLegacyHal : public WifiLegacyHal {
MOCK_METHOD3(nanDataInterfaceDelete,
wifi_error(const std::string&, transaction_id,
const std::string&));
MOCK_METHOD2(createVirtualInterface,
wifi_error(const std::string& ifname,
wifi_interface_type iftype));
MOCK_METHOD1(deleteVirtualInterface, wifi_error(const std::string& ifname));
};
} // namespace legacy_hal
} // namespace implementation

View file

@ -292,6 +292,7 @@ class WifiChipTest : public Test {
// mock).
property_set("wifi.interface", "wlan0");
property_set("wifi.concurrent.interface", "wlan1");
property_set("wifi.aware.interface", nullptr);
}
};
@ -773,6 +774,28 @@ TEST_F(WifiChipV2_AwareIfaceCombinationTest,
});
}
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNanWithSharedNanIface) {
property_set("wifi.aware.interface", nullptr);
findModeAndConfigureForIfaceType(IfaceType::STA);
ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
ASSERT_EQ(createIface(IfaceType::NAN), "wlan0");
removeIface(IfaceType::NAN, "wlan0");
EXPECT_CALL(*iface_util_, setUpState(testing::_, testing::_)).Times(0);
}
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNanWithDedicatedNanIface) {
property_set("wifi.aware.interface", "aware0");
findModeAndConfigureForIfaceType(IfaceType::STA);
ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
EXPECT_CALL(*iface_util_, setUpState("aware0", true))
.WillOnce(testing::Return(true));
ASSERT_EQ(createIface(IfaceType::NAN), "aware0");
EXPECT_CALL(*iface_util_, setUpState("aware0", false))
.WillOnce(testing::Return(true));
removeIface(IfaceType::NAN, "aware0");
}
////////// V1 Iface Combinations when AP creation is disabled //////////
class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
public:

View file

@ -131,7 +131,7 @@ TEST_F(WifiNanIfaceTest, IfacEventHandlers_OnStateToggleOffOn) {
bind(CaptureIfaceEventHandlers, std::placeholders::_1,
std::placeholders::_2, &captured_iface_event_handlers)));
sp<WifiNanIface> nan_iface =
new WifiNanIface(kIfaceName, legacy_hal_, iface_util_);
new WifiNanIface(kIfaceName, false, legacy_hal_, iface_util_);
// Register a mock nan event callback.
sp<NiceMock<MockNanIfaceEventCallback>> mock_event_callback{

View file

@ -107,6 +107,15 @@ std::string getP2pIfaceName() {
return buffer.data();
}
// Returns the dedicated iface name if one is defined.
std::string getNanIfaceName() {
std::array<char, PROPERTY_VALUE_MAX> buffer;
if (property_get("wifi.aware.interface", buffer.data(), nullptr) == 0) {
return {};
}
return buffer.data();
}
void setActiveWlanIfaceNameProperty(const std::string& ifname) {
auto res = property_set(kActiveWlanIfaceNameProperty, ifname.data());
if (res != 0) {
@ -864,9 +873,16 @@ std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() {
if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::NAN)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
// These are still assumed to be based on wlan0.
std::string ifname = getFirstActiveWlanIfaceName();
sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_, iface_util_);
bool is_dedicated_iface = true;
std::string ifname = getNanIfaceName();
if (ifname.empty()) {
// Use the first shared STA iface (wlan0) if a dedicated aware iface is
// not defined.
ifname = getFirstActiveWlanIfaceName();
is_dedicated_iface = false;
}
sp<WifiNanIface> iface =
new WifiNanIface(ifname, is_dedicated_iface, legacy_hal_, iface_util_);
nan_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {

View file

@ -110,6 +110,14 @@ std::array<uint8_t, 6> WifiIfaceUtil::createRandomMacAddress() {
address[0] &= ~kMacAddressMulticastMask;
return address;
}
bool WifiIfaceUtil::setUpState(const std::string& iface_name, bool request_up) {
if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), request_up)) {
LOG(ERROR) << "SetUpState to " << request_up << " failed";
return false;
}
return true;
}
} // namespace iface_util
} // namespace implementation
} // namespace V1_4

View file

@ -56,6 +56,7 @@ class WifiIfaceUtil {
virtual void registerIfaceEventHandlers(const std::string& iface_name,
IfaceEventHandlers handlers);
virtual void unregisterIfaceEventHandlers(const std::string& iface_name);
virtual bool setUpState(const std::string& iface_name, bool request_up);
private:
std::array<uint8_t, 6> createRandomMacAddress();

View file

@ -373,9 +373,9 @@ class WifiLegacyHal {
std::array<int8_t, 2> code);
// interface functions.
wifi_error createVirtualInterface(const std::string& ifname,
wifi_interface_type iftype);
wifi_error deleteVirtualInterface(const std::string& ifname);
virtual wifi_error createVirtualInterface(const std::string& ifname,
wifi_interface_type iftype);
virtual wifi_error deleteVirtualInterface(const std::string& ifname);
private:
// Retrieve interface handles for all the available interfaces.

View file

@ -29,13 +29,22 @@ namespace implementation {
using hidl_return_util::validateAndCall;
WifiNanIface::WifiNanIface(
const std::string& ifname,
const std::string& ifname, bool is_dedicated_iface,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
: ifname_(ifname),
is_dedicated_iface_(is_dedicated_iface),
legacy_hal_(legacy_hal),
iface_util_(iface_util),
is_valid_(true) {
if (is_dedicated_iface_) {
// If using a dedicated iface, set the iface up first.
if (!iface_util_.lock()->setUpState(ifname_, true)) {
// Fatal failure, invalidate the iface object.
invalidate();
return;
}
}
// Register all the callbacks here. these should be valid for the lifetime
// of the object. Whenever the mode changes legacy HAL will remove
// all of these callbacks.
@ -534,6 +543,10 @@ void WifiNanIface::invalidate() {
event_cb_handler_.invalidate();
event_cb_handler_1_2_.invalidate();
is_valid_ = false;
if (is_dedicated_iface_) {
// If using a dedicated iface, set the iface down.
iface_util_.lock()->setUpState(ifname_, false);
}
}
bool WifiNanIface::isValid() { return is_valid_; }

View file

@ -38,7 +38,7 @@ using namespace android::hardware::wifi::V1_2;
*/
class WifiNanIface : public V1_4::IWifiNanIface {
public:
WifiNanIface(const std::string& ifname,
WifiNanIface(const std::string& ifname, bool is_dedicated_iface,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
// Refer to |WifiChip::invalidate()|.
@ -165,6 +165,7 @@ class WifiNanIface : public V1_4::IWifiNanIface {
std::set<sp<V1_2::IWifiNanIfaceEventCallback>> getEventCallbacks_1_2();
std::string ifname_;
bool is_dedicated_iface_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
bool is_valid_;