Merge changes I760dc5ca,Ia2da1dcf into qt-dev

* changes:
  wifi(implementation): Send NAN disabled on wlan0 down & up
  wifi(implementation): Invalidate NAN iface on STA iface removal
This commit is contained in:
Roshan Pius 2019-05-24 06:20:55 +00:00 committed by Android (Google) Code Review
commit c733f3bbed
9 changed files with 166 additions and 6 deletions

View file

@ -700,6 +700,72 @@ TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) {
});
}
TEST_F(WifiChipV2_AwareIfaceCombinationTest,
InvalidateAndRemoveNanOnStaRemove) {
findModeAndConfigureForIfaceType(IfaceType::STA);
ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
// Create NAN iface
ASSERT_EQ(createIface(IfaceType::NAN), "wlan0");
// We should have 1 nan iface.
chip_->getNanIfaceNames(
[](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) {
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
ASSERT_EQ(iface_names.size(), 1u);
ASSERT_EQ(iface_names[0], "wlan0");
});
// Retrieve the exact iface object.
sp<IWifiNanIface> nan_iface;
chip_->getNanIface("wlan0", [&nan_iface](const WifiStatus& status,
const sp<IWifiNanIface>& iface) {
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
ASSERT_NE(iface.get(), nullptr);
nan_iface = iface;
});
// Remove the STA iface.
removeIface(IfaceType::STA, "wlan0");
// We should have 0 nan iface now.
chip_->getNanIfaceNames(
[](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) {
ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
ASSERT_EQ(iface_names.size(), 0u);
});
// Any operation on the nan iface object should return error now.
nan_iface->getName(
[](const WifiStatus& status, const std::string& /* iface_name */) {
ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID, status.code);
});
}
TEST_F(WifiChipV2_AwareIfaceCombinationTest,
InvalidateAndRemoveRttControllerOnStaRemove) {
findModeAndConfigureForIfaceType(IfaceType::STA);
ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
// Create RTT controller
sp<IWifiRttController> rtt_controller;
chip_->createRttController(
NULL, [&rtt_controller](const WifiStatus& status,
const sp<IWifiRttController>& rtt) {
if (WifiStatusCode::SUCCESS == status.code) {
ASSERT_NE(rtt.get(), nullptr);
rtt_controller = rtt;
}
});
// Remove the STA iface.
removeIface(IfaceType::STA, "wlan0");
// Any operation on the rtt controller object should return error now.
rtt_controller->getBoundIface(
[](const WifiStatus& status, const sp<IWifiIface>& /* iface */) {
ASSERT_EQ(WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
status.code);
});
}
////////// V1 Iface Combinations when AP creation is disabled //////////
class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
public:
@ -732,6 +798,7 @@ TEST_F(WifiChipV2_AwareDisabledApIfaceCombinationTest,
ASSERT_TRUE(createIface(IfaceType::AP).empty());
}
////////// Hypothetical Iface Combination with multiple ifaces //////////
class WifiChip_MultiIfaceTest : public WifiChipTest {
public:
void SetUp() override {

View file

@ -634,6 +634,27 @@ void WifiChip::invalidateAndRemoveAllIfaces() {
rtt_controllers_.clear();
}
void WifiChip::invalidateAndRemoveDependencies(
const std::string& removed_iface_name) {
for (const auto& nan_iface : nan_ifaces_) {
if (nan_iface->getName() == removed_iface_name) {
invalidateAndClear(nan_ifaces_, nan_iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback
->onIfaceRemoved(IfaceType::NAN, removed_iface_name)
.isOk()) {
LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
}
}
}
}
for (const auto& rtt : rtt_controllers_) {
if (rtt->getIfaceName() == removed_iface_name) {
invalidateAndClear(rtt_controllers_, rtt);
}
}
}
std::pair<WifiStatus, ChipId> WifiChip::getIdInternal() {
return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_};
}
@ -819,6 +840,11 @@ WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
if (!iface.get()) {
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
}
// Invalidate & remove any dependent objects first.
// Note: This is probably not required because we never create
// nan/rtt objects over AP iface. But, there is no harm to do it
// here and not make that assumption all over the place.
invalidateAndRemoveDependencies(ifname);
invalidateAndClear(ap_ifaces_, iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
@ -835,7 +861,7 @@ std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() {
}
// These are still assumed to be based on wlan0.
std::string ifname = getFirstActiveWlanIfaceName();
sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_);
sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_, iface_util_);
nan_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
@ -960,6 +986,8 @@ WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) {
if (!iface.get()) {
return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
}
// Invalidate & remove any dependent objects first.
invalidateAndRemoveDependencies(ifname);
invalidateAndClear(sta_ifaces_, iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {

View file

@ -155,6 +155,9 @@ class WifiChip : public V1_3::IWifiChip {
private:
void invalidateAndRemoveAllIfaces();
// When a STA iface is removed any dependent NAN-ifaces/RTT-controllers are
// invalidated & removed.
void invalidateAndRemoveDependencies(const std::string& removed_iface_name);
// Corresponding worker functions for the HIDL methods.
std::pair<WifiStatus, ChipId> getIdInternal();

View file

@ -39,7 +39,8 @@ namespace V1_3 {
namespace implementation {
namespace iface_util {
WifiIfaceUtil::WifiIfaceUtil() : random_mac_address_(nullptr) {}
WifiIfaceUtil::WifiIfaceUtil()
: random_mac_address_(nullptr), event_handlers_map_() {}
std::array<uint8_t, 6> WifiIfaceUtil::getFactoryMacAddress(
const std::string& iface_name) {
@ -60,6 +61,14 @@ bool WifiIfaceUtil::setMacAddress(const std::string& iface_name,
LOG(ERROR) << "SetUpState(true) failed.";
return false;
}
IfaceEventHandlers event_handlers = {};
const auto it = event_handlers_map_.find(iface_name);
if (it != event_handlers_map_.end()) {
event_handlers = it->second;
}
if (event_handlers.on_state_toggle_off_on != nullptr) {
event_handlers.on_state_toggle_off_on(iface_name);
}
LOG(DEBUG) << "Successfully SetMacAddress.";
return true;
}
@ -73,6 +82,16 @@ std::array<uint8_t, 6> WifiIfaceUtil::getOrCreateRandomMacAddress() {
return *random_mac_address_.get();
}
void WifiIfaceUtil::registerIfaceEventHandlers(const std::string& iface_name,
IfaceEventHandlers handlers) {
event_handlers_map_[iface_name] = handlers;
}
void WifiIfaceUtil::unregisterIfaceEventHandlers(
const std::string& iface_name) {
event_handlers_map_.erase(iface_name);
}
std::array<uint8_t, 6> WifiIfaceUtil::createRandomMacAddress() {
std::array<uint8_t, 6> address = {};
std::random_device rd;

View file

@ -28,6 +28,13 @@ namespace V1_3 {
namespace implementation {
namespace iface_util {
// Iface event handlers.
struct IfaceEventHandlers {
// Callback to be invoked when the iface is set down & up for MAC address
// change.
std::function<void(const std::string& iface_name)> on_state_toggle_off_on;
};
/**
* Util class for common iface operations.
*/
@ -45,11 +52,17 @@ class WifiIfaceUtil {
// daemon. (So, changes on every reboot)
virtual std::array<uint8_t, 6> getOrCreateRandomMacAddress();
// Register for any iface event callbacks for the provided interface.
virtual void registerIfaceEventHandlers(const std::string& iface_name,
IfaceEventHandlers handlers);
virtual void unregisterIfaceEventHandlers(const std::string& iface_name);
private:
std::array<uint8_t, 6> createRandomMacAddress();
wifi_system::InterfaceTool iface_tool_;
std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_;
std::map<std::string, IfaceEventHandlers> event_handlers_map_;
};
} // namespace iface_util

View file

@ -30,8 +30,12 @@ using hidl_return_util::validateAndCall;
WifiNanIface::WifiNanIface(
const std::string& ifname,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
: ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
: ifname_(ifname),
legacy_hal_(legacy_hal),
iface_util_(iface_util),
is_valid_(true) {
// 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.
@ -498,6 +502,26 @@ WifiNanIface::WifiNanIface(
LOG(ERROR) << "Failed to register nan callbacks. Invalidating object";
invalidate();
}
// Register for iface state toggle events.
iface_util::IfaceEventHandlers event_handlers = {};
event_handlers.on_state_toggle_off_on =
[weak_ptr_this](const std::string& /* iface_name */) {
const auto shared_ptr_this = weak_ptr_this.promote();
if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
LOG(ERROR) << "Callback invoked on an invalid object";
return;
}
// Tell framework that NAN has been disabled.
WifiNanStatus status = {
NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
if (!callback->eventDisabled(status).isOk()) {
LOG(ERROR) << "Failed to invoke the callback";
}
}
};
iface_util_.lock()->registerIfaceEventHandlers(ifname_, event_handlers);
}
void WifiNanIface::invalidate() {
@ -505,7 +529,7 @@ void WifiNanIface::invalidate() {
legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF);
legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0");
legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFD, "aware_data1");
iface_util_.lock()->unregisterIfaceEventHandlers(ifname_);
legacy_hal_.reset();
event_cb_handler_.invalidate();
event_cb_handler_1_2_.invalidate();

View file

@ -22,6 +22,7 @@
#include <android/hardware/wifi/1.2/IWifiNanIface.h>
#include "hidl_callback_util.h"
#include "wifi_iface_util.h"
#include "wifi_legacy_hal.h"
namespace android {
@ -37,7 +38,8 @@ using namespace android::hardware::wifi::V1_0;
class WifiNanIface : public V1_2::IWifiNanIface {
public:
WifiNanIface(const std::string& ifname,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
// Refer to |WifiChip::invalidate()|.
void invalidate();
bool isValid();
@ -147,6 +149,7 @@ class WifiNanIface : public V1_2::IWifiNanIface {
std::string ifname_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
bool is_valid_;
hidl_callback_util::HidlCallbackHandler<V1_0::IWifiNanIfaceEventCallback>
event_cb_handler_;

View file

@ -49,6 +49,8 @@ WifiRttController::getEventCallbacks() {
return event_callbacks_;
}
std::string WifiRttController::getIfaceName() { return ifname_; }
Return<void> WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) {
return validateAndCall(
this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,

View file

@ -42,6 +42,7 @@ class WifiRttController : public V1_0::IWifiRttController {
void invalidate();
bool isValid();
std::vector<sp<IWifiRttControllerEventCallback>> getEventCallbacks();
std::string getIfaceName();
// HIDL methods exposed.
Return<void> getBoundIface(getBoundIface_cb hidl_status_cb) override;