Merge changes from topic "60ghz-1-vendor-hal-multi-chip"
* changes:
Wifi: support multiple WIFI chips
Wifi: fix bug during WIFI HAL stop
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
index 5b11dd3..092822f 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -112,7 +112,7 @@
const auto& status_and_chip_ids = HIDL_INVOKE(wifi, getChipIds);
const auto& chip_ids = status_and_chip_ids.second;
if (status_and_chip_ids.first.code != WifiStatusCode::SUCCESS ||
- chip_ids.size() != 1) {
+ chip_ids.size() < 1) {
return nullptr;
}
const auto& status_and_chip = HIDL_INVOKE(wifi, getChip, chip_ids[0]);
diff --git a/wifi/1.5/default/Android.mk b/wifi/1.5/default/Android.mk
index 236dae2..dc9e89b 100644
--- a/wifi/1.5/default/Android.mk
+++ b/wifi/1.5/default/Android.mk
@@ -51,6 +51,7 @@
wifi_feature_flags.cpp \
wifi_iface_util.cpp \
wifi_legacy_hal.cpp \
+ wifi_legacy_hal_factory.cpp \
wifi_legacy_hal_stubs.cpp \
wifi_mode_controller.cpp \
wifi_nan_iface.cpp \
@@ -67,12 +68,14 @@
libutils \
libwifi-hal \
libwifi-system-iface \
+ libxml2 \
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.5
+LOCAL_C_INCLUDES += $(TOP)/external/libxml2/include
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_STATIC_LIBRARY)
@@ -96,6 +99,7 @@
libutils \
libwifi-hal \
libwifi-system-iface \
+ libxml2 \
android.hardware.wifi@1.0 \
android.hardware.wifi@1.1 \
android.hardware.wifi@1.2 \
@@ -129,6 +133,7 @@
libutils \
libwifi-hal \
libwifi-system-iface \
+ libxml2 \
android.hardware.wifi@1.0 \
android.hardware.wifi@1.1 \
android.hardware.wifi@1.2 \
diff --git a/wifi/1.5/default/service.cpp b/wifi/1.5/default/service.cpp
index f53d528..8539a37 100644
--- a/wifi/1.5/default/service.cpp
+++ b/wifi/1.5/default/service.cpp
@@ -23,6 +23,7 @@
#include "wifi.h"
#include "wifi_feature_flags.h"
#include "wifi_legacy_hal.h"
+#include "wifi_legacy_hal_factory.h"
#include "wifi_mode_controller.h"
using android::hardware::configureRpcThreadpool;
@@ -32,6 +33,8 @@
WifiFeatureFlags;
using android::hardware::wifi::V1_5::implementation::iface_util::WifiIfaceUtil;
using android::hardware::wifi::V1_5::implementation::legacy_hal::WifiLegacyHal;
+using android::hardware::wifi::V1_5::implementation::legacy_hal::
+ WifiLegacyHalFactory;
using android::hardware::wifi::V1_5::implementation::mode_controller::
WifiModeController;
@@ -50,10 +53,13 @@
const auto iface_tool =
std::make_shared<android::wifi_system::InterfaceTool>();
+ const auto legacy_hal_factory =
+ std::make_shared<WifiLegacyHalFactory>(iface_tool);
+
// Setup hwbinder service
android::sp<android::hardware::wifi::V1_5::IWifi> service =
new android::hardware::wifi::V1_5::implementation::Wifi(
- iface_tool, std::make_shared<WifiLegacyHal>(iface_tool),
+ iface_tool, legacy_hal_factory,
std::make_shared<WifiModeController>(),
std::make_shared<WifiIfaceUtil>(iface_tool),
std::make_shared<WifiFeatureFlags>());
diff --git a/wifi/1.5/default/tests/mock_wifi_feature_flags.h b/wifi/1.5/default/tests/mock_wifi_feature_flags.h
index 92fbb05..c3877ed 100644
--- a/wifi/1.5/default/tests/mock_wifi_feature_flags.h
+++ b/wifi/1.5/default/tests/mock_wifi_feature_flags.h
@@ -33,7 +33,8 @@
public:
MockWifiFeatureFlags();
- MOCK_METHOD0(getChipModes, std::vector<V1_0::IWifiChip::ChipMode>());
+ MOCK_METHOD1(getChipModes,
+ std::vector<V1_0::IWifiChip::ChipMode>(bool is_primary));
MOCK_METHOD0(isApMacRandomizationDisabled, bool());
};
diff --git a/wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp b/wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp
index 501bd7f..d13c556 100644
--- a/wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp
@@ -29,8 +29,9 @@
namespace legacy_hal {
MockWifiLegacyHal::MockWifiLegacyHal(
- const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
- : WifiLegacyHal(iface_tool) {}
+ const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
+ const wifi_hal_fn& fn, bool is_primary)
+ : WifiLegacyHal(iface_tool, fn, is_primary) {}
} // namespace legacy_hal
} // namespace implementation
} // namespace V1_5
diff --git a/wifi/1.5/default/tests/mock_wifi_legacy_hal.h b/wifi/1.5/default/tests/mock_wifi_legacy_hal.h
index f938347..9ab2fd5 100644
--- a/wifi/1.5/default/tests/mock_wifi_legacy_hal.h
+++ b/wifi/1.5/default/tests/mock_wifi_legacy_hal.h
@@ -31,7 +31,8 @@
class MockWifiLegacyHal : public WifiLegacyHal {
public:
MockWifiLegacyHal(
- const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
+ const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
+ const wifi_hal_fn& fn, bool is_primary);
MOCK_METHOD0(initialize, wifi_error());
MOCK_METHOD0(start, wifi_error());
MOCK_METHOD2(stop, wifi_error(std::unique_lock<std::recursive_mutex>*,
diff --git a/wifi/1.5/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.5/default/tests/wifi_chip_unit_tests.cpp
index 1d55e16..d99bfbd 100644
--- a/wifi/1.5/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.5/default/tests/wifi_chip_unit_tests.cpp
@@ -59,7 +59,7 @@
{feature_flags::chip_mode_ids::kV1Ap, combinationsAp}
};
// clang-format on
- EXPECT_CALL(*feature_flags_, getChipModes())
+ EXPECT_CALL(*feature_flags_, getChipModes(true))
.WillRepeatedly(testing::Return(modes));
}
@@ -76,7 +76,7 @@
{feature_flags::chip_mode_ids::kV1Ap, combinationsAp}
};
// clang-format on
- EXPECT_CALL(*feature_flags_, getChipModes())
+ EXPECT_CALL(*feature_flags_, getChipModes(true))
.WillRepeatedly(testing::Return(modes));
}
@@ -89,7 +89,7 @@
{feature_flags::chip_mode_ids::kV1Sta, combinationsSta}
};
// clang-format on
- EXPECT_CALL(*feature_flags_, getChipModes())
+ EXPECT_CALL(*feature_flags_, getChipModes(true))
.WillRepeatedly(testing::Return(modes));
}
@@ -103,7 +103,7 @@
{feature_flags::chip_mode_ids::kV3, combinations}
};
// clang-format on
- EXPECT_CALL(*feature_flags_, getChipModes())
+ EXPECT_CALL(*feature_flags_, getChipModes(true))
.WillRepeatedly(testing::Return(modes));
}
@@ -116,7 +116,7 @@
{feature_flags::chip_mode_ids::kV3, combinations}
};
// clang-format on
- EXPECT_CALL(*feature_flags_, getChipModes())
+ EXPECT_CALL(*feature_flags_, getChipModes(true))
.WillRepeatedly(testing::Return(modes));
}
@@ -129,7 +129,7 @@
{feature_flags::chip_mode_ids::kV3, combinations}
};
// clang-format on
- EXPECT_CALL(*feature_flags_, getChipModes())
+ EXPECT_CALL(*feature_flags_, getChipModes(true))
.WillRepeatedly(testing::Return(modes));
}
@@ -267,10 +267,12 @@
sp<WifiChip> chip_;
ChipId chip_id_ = kFakeChipId;
+ legacy_hal::wifi_hal_fn fake_func_table_;
std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
new NiceMock<wifi_system::MockInterfaceTool>};
std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
- new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_)};
+ new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_,
+ fake_func_table_, true)};
std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>>
mode_controller_{new NiceMock<mode_controller::MockWifiModeController>};
std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
@@ -281,8 +283,8 @@
public:
void SetUp() override {
chip_ =
- new WifiChip(chip_id_, legacy_hal_, mode_controller_, iface_util_,
- feature_flags_, subsystemRestartHandler);
+ new WifiChip(chip_id_, true, legacy_hal_, mode_controller_,
+ iface_util_, feature_flags_, subsystemRestartHandler);
EXPECT_CALL(*mode_controller_, changeFirmwareMode(testing::_))
.WillRepeatedly(testing::Return(true));
diff --git a/wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp
index 3e7026f..411190b 100644
--- a/wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp
+++ b/wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp
@@ -112,10 +112,12 @@
class WifiNanIfaceTest : public Test {
protected:
+ legacy_hal::wifi_hal_fn fake_func_table_;
std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
new NiceMock<wifi_system::MockInterfaceTool>};
std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
- new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_)};
+ new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_,
+ fake_func_table_, true)};
std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_)};
};
diff --git a/wifi/1.5/default/wifi.cpp b/wifi/1.5/default/wifi.cpp
index c4e2333..17db51d 100644
--- a/wifi/1.5/default/wifi.cpp
+++ b/wifi/1.5/default/wifi.cpp
@@ -21,8 +21,8 @@
#include "wifi_status_util.h"
namespace {
-// Chip ID to use for the only supported chip.
-static constexpr android::hardware::wifi::V1_0::ChipId kChipId = 0;
+// Starting Chip ID, will be assigned to primary chip
+static constexpr android::hardware::wifi::V1_0::ChipId kPrimaryChipId = 0;
} // namespace
namespace android {
@@ -35,12 +35,12 @@
Wifi::Wifi(
const std::shared_ptr<wifi_system::InterfaceTool> iface_tool,
- const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory,
const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags)
: iface_tool_(iface_tool),
- legacy_hal_(legacy_hal),
+ legacy_hal_factory_(legacy_hal_factory),
mode_controller_(mode_controller),
iface_util_(iface_util),
feature_flags_(feature_flags),
@@ -84,10 +84,16 @@
Return<void> Wifi::debug(const hidl_handle& handle,
const hidl_vec<hidl_string>&) {
LOG(INFO) << "-----------Debug is called----------------";
- if (!chip_.get()) {
+ if (chips_.size() == 0) {
return Void();
}
- return chip_->debug(handle, {});
+
+ for (sp<WifiChip> chip : chips_) {
+ if (!chip.get()) continue;
+
+ chip->debug(handle, {});
+ }
+ return Void();
}
WifiStatus Wifi::registerEventCallbackInternal(
@@ -120,10 +126,13 @@
};
// Create the chip instance once the HAL is started.
- // Need to consider the case of multiple chips TODO(156998862)
- chip_ =
- new WifiChip(kChipId, legacy_hal_, mode_controller_, iface_util_,
- feature_flags_, on_subsystem_restart_callback);
+ android::hardware::wifi::V1_0::ChipId chipId = kPrimaryChipId;
+ for (auto& hal : legacy_hals_) {
+ chips_.push_back(new WifiChip(
+ chipId, chipId == kPrimaryChipId, hal, mode_controller_,
+ iface_util_, feature_flags_, on_subsystem_restart_callback));
+ chipId++;
+ }
run_state_ = RunState::STARTED;
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onStart().isOk()) {
@@ -154,10 +163,13 @@
}
// Clear the chip object and its child objects since the HAL is now
// stopped.
- if (chip_.get()) {
- chip_->invalidate();
- chip_.clear();
+ for (auto& chip : chips_) {
+ if (chip.get()) {
+ chip->invalidate();
+ chip.clear();
+ }
}
+ chips_.clear();
WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock);
if (wifi_status.code == WifiStatusCode::SUCCESS) {
for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -181,21 +193,23 @@
std::pair<WifiStatus, std::vector<ChipId>> Wifi::getChipIdsInternal() {
std::vector<ChipId> chip_ids;
- if (chip_.get()) {
- chip_ids.emplace_back(kChipId);
+
+ for (auto& chip : chips_) {
+ ChipId chip_id = getChipIdFromWifiChip(chip);
+ if (chip_id != UINT32_MAX) chip_ids.emplace_back(chip_id);
}
return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)};
}
std::pair<WifiStatus, sp<V1_4::IWifiChip>> Wifi::getChipInternal(
ChipId chip_id) {
- if (!chip_.get()) {
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_STARTED), nullptr};
+ for (auto& chip : chips_) {
+ ChipId cand_id = getChipIdFromWifiChip(chip);
+ if ((cand_id != UINT32_MAX) && (cand_id == chip_id))
+ return {createWifiStatus(WifiStatusCode::SUCCESS), chip};
}
- if (chip_id != kChipId) {
- return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), chip_};
+
+ return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
}
WifiStatus Wifi::initializeModeControllerAndLegacyHal() {
@@ -203,23 +217,46 @@
LOG(ERROR) << "Failed to initialize firmware mode controller";
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
}
- legacy_hal::wifi_error legacy_status = legacy_hal_->initialize();
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to initialize legacy HAL: "
- << legacyErrorToString(legacy_status);
- return createWifiStatusFromLegacyError(legacy_status);
+
+ legacy_hals_ = legacy_hal_factory_->getHals();
+ if (legacy_hals_.empty())
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ int index = 0; // for failure log
+ for (auto& hal : legacy_hals_) {
+ legacy_hal::wifi_error legacy_status = hal->initialize();
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ // Currently WifiLegacyHal::initialize does not allocate extra mem,
+ // only initializes the function table. If this changes, need to
+ // implement WifiLegacyHal::deinitialize and deinitalize the
+ // HALs already initialized
+ LOG(ERROR) << "Failed to initialize legacy HAL index: " << index
+ << " error: " << legacyErrorToString(legacy_status);
+ return createWifiStatusFromLegacyError(legacy_status);
+ }
+ index++;
}
return createWifiStatus(WifiStatusCode::SUCCESS);
}
WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController(
/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
+ legacy_hal::wifi_error legacy_status = legacy_hal::WIFI_SUCCESS;
+ int index = 0;
+
run_state_ = RunState::STOPPING;
- legacy_hal::wifi_error legacy_status =
- legacy_hal_->stop(lock, [&]() { run_state_ = RunState::STOPPED; });
+ for (auto& hal : legacy_hals_) {
+ legacy_hal::wifi_error tmp = hal->stop(lock, [&]() {});
+ if (tmp != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to stop legacy HAL index: " << index
+ << " error: " << legacyErrorToString(legacy_status);
+ legacy_status = tmp;
+ }
+ index++;
+ }
+ run_state_ = RunState::STOPPED;
+
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to stop legacy HAL: "
- << legacyErrorToString(legacy_status);
+ LOG(ERROR) << "One or more legacy HALs failed to stop";
return createWifiStatusFromLegacyError(legacy_status);
}
if (!mode_controller_->deinitialize()) {
@@ -228,6 +265,19 @@
}
return createWifiStatus(WifiStatusCode::SUCCESS);
}
+
+ChipId Wifi::getChipIdFromWifiChip(sp<WifiChip>& chip) {
+ ChipId chip_id = UINT32_MAX;
+ if (chip.get()) {
+ chip->getId([&](WifiStatus status, uint32_t id) {
+ if (status.code == WifiStatusCode::SUCCESS) {
+ chip_id = id;
+ }
+ });
+ }
+
+ return chip_id;
+}
} // namespace implementation
} // namespace V1_5
} // namespace wifi
diff --git a/wifi/1.5/default/wifi.h b/wifi/1.5/default/wifi.h
index 8de0ef4..9f5a1b0 100644
--- a/wifi/1.5/default/wifi.h
+++ b/wifi/1.5/default/wifi.h
@@ -27,6 +27,7 @@
#include "wifi_chip.h"
#include "wifi_feature_flags.h"
#include "wifi_legacy_hal.h"
+#include "wifi_legacy_hal_factory.h"
#include "wifi_mode_controller.h"
namespace android {
@@ -41,7 +42,8 @@
class Wifi : public V1_5::IWifi {
public:
Wifi(const std::shared_ptr<wifi_system::InterfaceTool> iface_tool,
- const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::shared_ptr<legacy_hal::WifiLegacyHalFactory>
+ legacy_hal_factory,
const std::shared_ptr<mode_controller::WifiModeController>
mode_controller,
const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
@@ -75,16 +77,18 @@
WifiStatus initializeModeControllerAndLegacyHal();
WifiStatus stopLegacyHalAndDeinitializeModeController(
std::unique_lock<std::recursive_mutex>* lock);
+ ChipId getChipIdFromWifiChip(sp<WifiChip>& chip);
// Instance is created in this root level |IWifi| HIDL interface object
// and shared with all the child HIDL interface objects.
std::shared_ptr<wifi_system::InterfaceTool> iface_tool_;
- std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+ std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory_;
std::shared_ptr<mode_controller::WifiModeController> mode_controller_;
+ std::vector<std::shared_ptr<legacy_hal::WifiLegacyHal>> legacy_hals_;
std::shared_ptr<iface_util::WifiIfaceUtil> iface_util_;
std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
RunState run_state_;
- sp<WifiChip> chip_;
+ std::vector<sp<WifiChip>> chips_;
hidl_callback_util::HidlCallbackHandler<IWifiEventCallback>
event_cb_handler_;
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 069fd65..9c352bc 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -332,7 +332,8 @@
using hidl_return_util::validateAndCallWithLock;
WifiChip::WifiChip(
- ChipId chip_id, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ ChipId chip_id, bool is_primary,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util,
const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
@@ -343,7 +344,7 @@
iface_util_(iface_util),
is_valid_(true),
current_mode_id_(feature_flags::chip_mode_ids::kInvalid),
- modes_(feature_flags.lock()->getChipModes()),
+ modes_(feature_flags.lock()->getChipModes(is_primary)),
debug_ring_buffer_cb_registered_(false),
subsystemCallbackHandler_(handler) {
setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue);
@@ -681,9 +682,10 @@
void WifiChip::invalidateAndRemoveDependencies(
const std::string& removed_iface_name) {
- for (const auto& nan_iface : nan_ifaces_) {
+ for (auto it = nan_ifaces_.begin(); it != nan_ifaces_.end();) {
+ auto nan_iface = *it;
if (nan_iface->getName() == removed_iface_name) {
- invalidateAndClear(nan_ifaces_, nan_iface);
+ nan_iface->invalidate();
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback
->onIfaceRemoved(IfaceType::NAN, removed_iface_name)
@@ -691,11 +693,19 @@
LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
}
}
+ it = nan_ifaces_.erase(it);
+ } else {
+ ++it;
}
}
- for (const auto& rtt : rtt_controllers_) {
+
+ for (auto it = rtt_controllers_.begin(); it != rtt_controllers_.end();) {
+ auto rtt = *it;
if (rtt->getIfaceName() == removed_iface_name) {
- invalidateAndClear(rtt_controllers_, rtt);
+ rtt->invalidate();
+ it = rtt_controllers_.erase(it);
+ } else {
+ ++it;
}
}
}
@@ -1590,15 +1600,16 @@
// This could happen if the chip call is made before any STA/AP
// iface is created. Default to wlan0 for such cases.
LOG(WARNING) << "No active wlan interfaces in use! Using default";
- return getWlanIfaceName(0);
+ return getWlanIfaceNameWithType(IfaceType::STA, 0);
}
// Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx|
// not already in use.
// Note: This doesn't check the actual presence of these interfaces.
-std::string WifiChip::allocateApOrStaIfaceName(uint32_t start_idx) {
+std::string WifiChip::allocateApOrStaIfaceName(IfaceType type,
+ uint32_t start_idx) {
for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) {
- const auto ifname = getWlanIfaceName(idx);
+ const auto ifname = getWlanIfaceNameWithType(type, idx);
if (findUsingName(ap_ifaces_, ifname)) continue;
if (findUsingName(sta_ifaces_, ifname)) continue;
return ifname;
@@ -1616,7 +1627,8 @@
if (!ifname.empty()) {
return ifname;
}
- return allocateApOrStaIfaceName((isStaApConcurrencyAllowedInCurrentMode() &&
+ return allocateApOrStaIfaceName(IfaceType::AP,
+ (isStaApConcurrencyAllowedInCurrentMode() &&
!isDualApAllowedInCurrentMode())
? 1
: 0);
@@ -1625,7 +1637,7 @@
// STA iface names start with idx 0.
// Primary STA iface will always be 0.
std::string WifiChip::allocateStaIfaceName() {
- return allocateApOrStaIfaceName(0);
+ return allocateApOrStaIfaceName(IfaceType::STA, 0);
}
bool WifiChip::writeRingbufferFilesInternal() {
@@ -1661,6 +1673,17 @@
return true;
}
+std::string WifiChip::getWlanIfaceNameWithType(IfaceType type, unsigned idx) {
+ std::string ifname;
+
+ // let the legacy hal override the interface name
+ legacy_hal::wifi_error err =
+ legacy_hal_.lock()->getSupportedIfaceName((uint32_t)type, ifname);
+ if (err == legacy_hal::WIFI_SUCCESS) return ifname;
+
+ return getWlanIfaceName(idx);
+}
+
} // namespace implementation
} // namespace V1_5
} // namespace wifi
diff --git a/wifi/1.5/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h
index 36c191c..5f1d9e8 100644
--- a/wifi/1.5/default/wifi_chip.h
+++ b/wifi/1.5/default/wifi_chip.h
@@ -50,7 +50,7 @@
*/
class WifiChip : public V1_4::IWifiChip {
public:
- WifiChip(ChipId chip_id,
+ WifiChip(ChipId chip_id, bool is_primary,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::weak_ptr<mode_controller::WifiModeController>
mode_controller,
@@ -256,10 +256,11 @@
bool isStaApConcurrencyAllowedInCurrentMode();
bool isDualApAllowedInCurrentMode();
std::string getFirstActiveWlanIfaceName();
- std::string allocateApOrStaIfaceName(uint32_t start_idx);
+ std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx);
std::string allocateApIfaceName();
std::string allocateStaIfaceName();
bool writeRingbufferFilesInternal();
+ std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx);
ChipId chip_id_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
diff --git a/wifi/1.5/default/wifi_feature_flags.cpp b/wifi/1.5/default/wifi_feature_flags.cpp
index 151d473..9f91bd7 100644
--- a/wifi/1.5/default/wifi_feature_flags.cpp
+++ b/wifi/1.5/default/wifi_feature_flags.cpp
@@ -139,6 +139,13 @@
ChipIfaceCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_AP})},
#endif
};
+
+static const std::vector<IWifiChip::ChipMode> kChipModesSecondary{
+#ifdef WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP
+ {chip_mode_ids::kV3, ChipIfaceCombination::make_vec(
+ {WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP})},
+#endif
+};
#undef STA
#undef AP
#undef P2P
@@ -154,8 +161,9 @@
WifiFeatureFlags::WifiFeatureFlags() {}
-std::vector<IWifiChip::ChipMode> WifiFeatureFlags::getChipModes() {
- return kChipModes;
+std::vector<IWifiChip::ChipMode> WifiFeatureFlags::getChipModes(
+ bool is_primary) {
+ return (is_primary) ? kChipModes : kChipModesSecondary;
}
} // namespace feature_flags
diff --git a/wifi/1.5/default/wifi_feature_flags.h b/wifi/1.5/default/wifi_feature_flags.h
index 73d18ec..cb68b8c 100644
--- a/wifi/1.5/default/wifi_feature_flags.h
+++ b/wifi/1.5/default/wifi_feature_flags.h
@@ -42,7 +42,8 @@
WifiFeatureFlags();
virtual ~WifiFeatureFlags() = default;
- virtual std::vector<V1_0::IWifiChip::ChipMode> getChipModes();
+ virtual std::vector<V1_0::IWifiChip::ChipMode> getChipModes(
+ bool is_primary);
};
} // namespace feature_flags
diff --git a/wifi/1.5/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp
index 4070568..6ee8937 100644
--- a/wifi/1.5/default/wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal.cpp
@@ -36,7 +36,8 @@
static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
static constexpr uint32_t kMaxRingBuffers = 10;
-static constexpr uint32_t kMaxStopCompleteWaitMs = 100;
+// need a long timeout (1000ms) for chips that unload their driver.
+static constexpr uint32_t kMaxStopCompleteWaitMs = 1000;
static constexpr char kDriverPropName[] = "wlan.driver.status";
// Helper function to create a non-const char* for legacy Hal API's.
@@ -54,6 +55,7 @@
namespace V1_5 {
namespace implementation {
namespace legacy_hal {
+
// Legacy HAL functions accept "C" style function pointers, so use global
// functions to pass to the legacy HAL function and store the corresponding
// std::function methods to be invoked.
@@ -344,26 +346,20 @@
// End of the free-standing "C" style callbacks.
WifiLegacyHal::WifiLegacyHal(
- const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
- : global_handle_(nullptr),
+ const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
+ const wifi_hal_fn& fn, bool is_primary)
+ : global_func_table_(fn),
+ global_handle_(nullptr),
awaiting_event_loop_termination_(false),
is_started_(false),
- iface_tool_(iface_tool) {}
+ iface_tool_(iface_tool),
+ is_primary_(is_primary) {}
wifi_error WifiLegacyHal::initialize() {
LOG(DEBUG) << "Initialize legacy HAL";
- // TODO: Add back the HAL Tool if we need to. All we need from the HAL tool
- // for now is this function call which we can directly call.
- if (!initHalFuncTableWithStubs(&global_func_table_)) {
- LOG(ERROR)
- << "Failed to initialize legacy hal function table with stubs";
- return WIFI_ERROR_UNKNOWN;
- }
- wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_);
- if (status != WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to initialize legacy hal function table";
- }
- return status;
+ // this now does nothing, since HAL function table is provided
+ // to the constructor
+ return WIFI_SUCCESS;
}
wifi_error WifiLegacyHal::start() {
@@ -380,13 +376,17 @@
LOG(ERROR) << "Timed out awaiting driver ready";
return status;
}
- property_set(kDriverPropName, "ok");
+
+ if (is_primary_) {
+ property_set(kDriverPropName, "ok");
+
+ if (!iface_tool_.lock()->SetWifiUpState(true)) {
+ LOG(ERROR) << "Failed to set WiFi interface up";
+ return WIFI_ERROR_UNKNOWN;
+ }
+ }
LOG(DEBUG) << "Starting legacy HAL";
- if (!iface_tool_.lock()->SetWifiUpState(true)) {
- LOG(ERROR) << "Failed to set WiFi interface up";
- return WIFI_ERROR_UNKNOWN;
- }
status = global_func_table_.wifi_initialize(&global_handle_);
if (status != WIFI_SUCCESS || !global_handle_) {
LOG(ERROR) << "Failed to retrieve global handle";
@@ -419,7 +419,7 @@
// Invalidate all the internal pointers now that the HAL is
// stopped.
invalidate();
- iface_tool_.lock()->SetWifiUpState(false);
+ if (is_primary_) iface_tool_.lock()->SetWifiUpState(false);
on_stop_complete_user_callback();
is_started_ = false;
};
@@ -488,12 +488,21 @@
std::pair<wifi_error, uint32_t> WifiLegacyHal::getSupportedFeatureSet(
const std::string& iface_name) {
- feature_set set;
+ feature_set set = 0, chip_set = 0;
+ wifi_error status = WIFI_SUCCESS;
+
static_assert(sizeof(set) == sizeof(uint64_t),
"Some feature_flags can not be represented in output");
- wifi_error status = global_func_table_.wifi_get_supported_feature_set(
- getIfaceHandle(iface_name), &set);
- return {status, static_cast<uint32_t>(set)};
+ wifi_interface_handle iface_handle = getIfaceHandle(iface_name);
+
+ global_func_table_.wifi_get_chip_feature_set(
+ global_handle_, &chip_set); /* ignore error, chip_set will stay 0 */
+
+ if (iface_handle) {
+ status = global_func_table_.wifi_get_supported_feature_set(iface_handle,
+ &set);
+ }
+ return {status, static_cast<uint32_t>(set | chip_set)};
}
std::pair<wifi_error, PacketFilterCapabilities>
@@ -845,10 +854,15 @@
std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet(
const std::string& iface_name) {
- uint32_t supported_feature_flags;
- wifi_error status =
- global_func_table_.wifi_get_logger_supported_feature_set(
- getIfaceHandle(iface_name), &supported_feature_flags);
+ uint32_t supported_feature_flags = 0;
+ wifi_error status = WIFI_SUCCESS;
+
+ wifi_interface_handle iface_handle = getIfaceHandle(iface_name);
+
+ if (iface_handle) {
+ status = global_func_table_.wifi_get_logger_supported_feature_set(
+ iface_handle, &supported_feature_flags);
+ }
return {status, supported_feature_flags};
}
@@ -1485,6 +1499,17 @@
return status;
}
+wifi_error WifiLegacyHal::getSupportedIfaceName(uint32_t iface_type,
+ std::string& ifname) {
+ std::array<char, IFNAMSIZ> buffer;
+
+ wifi_error res = global_func_table_.wifi_get_supported_iface_name(
+ global_handle_, (uint32_t)iface_type, buffer.data(), buffer.size());
+ if (res == WIFI_SUCCESS) ifname = buffer.data();
+
+ return res;
+}
+
void WifiLegacyHal::invalidate() {
global_handle_ = nullptr;
iface_name_to_handle_.clear();
diff --git a/wifi/1.5/default/wifi_legacy_hal.h b/wifi/1.5/default/wifi_legacy_hal.h
index ae520a8..2984a00 100644
--- a/wifi/1.5/default/wifi_legacy_hal.h
+++ b/wifi/1.5/default/wifi_legacy_hal.h
@@ -173,7 +173,8 @@
*/
class WifiLegacyHal {
public:
- WifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
+ WifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
+ const wifi_hal_fn& fn, bool is_primary);
virtual ~WifiLegacyHal() = default;
// Initialize the legacy HAL function table.
@@ -379,6 +380,7 @@
virtual wifi_error createVirtualInterface(const std::string& ifname,
wifi_interface_type iftype);
virtual wifi_error deleteVirtualInterface(const std::string& ifname);
+ wifi_error getSupportedIfaceName(uint32_t iface_type, std::string& ifname);
private:
// Retrieve interface handles for all the available interfaces.
@@ -408,6 +410,11 @@
// Flag to indicate if the legacy HAL has been started.
bool is_started_;
std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
+ // flag to indicate if this HAL is for the primary chip. This is used
+ // in order to avoid some hard-coded behavior used with older HALs,
+ // such as bring wlan0 interface up/down on start/stop HAL.
+ // it may be removed once vendor HALs are updated.
+ bool is_primary_;
};
} // namespace legacy_hal
diff --git a/wifi/1.5/default/wifi_legacy_hal_factory.cpp b/wifi/1.5/default/wifi_legacy_hal_factory.cpp
new file mode 100644
index 0000000..fbaa284
--- /dev/null
+++ b/wifi/1.5/default/wifi_legacy_hal_factory.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2020 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 <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <android-base/logging.h>
+#include <dlfcn.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+
+#include "wifi_legacy_hal_factory.h"
+#include "wifi_legacy_hal_stubs.h"
+
+namespace {
+static constexpr char kVendorHalsDescPath[] = "/vendor/etc/wifi/vendor_hals";
+static constexpr char kVendorHalsDescExt[] = ".xml";
+static constexpr uint32_t kVendorHalsDescVersion = 1;
+
+bool isDirectory(struct dirent* entryPtr) {
+ bool isDir = false;
+ if (entryPtr->d_type != DT_UNKNOWN && entryPtr->d_type != DT_LNK) {
+ isDir = (entryPtr->d_type == DT_DIR);
+ } else {
+ struct stat entryStat;
+ stat(entryPtr->d_name, &entryStat);
+ isDir = S_ISDIR(entryStat.st_mode);
+ }
+ return isDir;
+}
+
+bool isFileExtension(const char* name, const char* ext) {
+ if (name == NULL) return false;
+ if (ext == NULL) return false;
+
+ size_t extLen = strlen(ext);
+ size_t nameLen = strlen(name);
+
+ if (extLen > nameLen) return false;
+
+ if (strncmp(name + nameLen - extLen, ext, extLen) != 0) return false;
+
+ return true;
+}
+}; // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_5 {
+namespace implementation {
+namespace legacy_hal {
+
+WifiLegacyHalFactory::WifiLegacyHalFactory(
+ const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
+ : iface_tool_(iface_tool) {}
+
+std::vector<std::shared_ptr<WifiLegacyHal>> WifiLegacyHalFactory::getHals() {
+ if (legacy_hals_.empty()) {
+ if (!initVendorHalDescriptorFromLinked())
+ initVendorHalsDescriptorList();
+ for (auto& desc : descs_) {
+ std::shared_ptr<WifiLegacyHal> hal =
+ std::make_shared<WifiLegacyHal>(iface_tool_, desc.fn,
+ desc.primary);
+ legacy_hals_.push_back(hal);
+ }
+ }
+
+ return legacy_hals_;
+}
+
+bool WifiLegacyHalFactory::initVendorHalDescriptorFromLinked() {
+ wifi_hal_lib_desc desc;
+
+ if (!initLinkedHalFunctionTable(&desc.fn)) return false;
+
+ desc.primary = true;
+ desc.handle = NULL;
+ descs_.push_back(desc);
+ return true;
+}
+
+bool WifiLegacyHalFactory::initLinkedHalFunctionTable(wifi_hal_fn* hal_fn) {
+ init_wifi_vendor_hal_func_table_t initfn;
+
+ initfn = (init_wifi_vendor_hal_func_table_t)dlsym(
+ RTLD_DEFAULT, "init_wifi_vendor_hal_func_table");
+ if (!initfn) {
+ LOG(INFO) << "no vendor HAL library linked, will try dynamic load";
+ return false;
+ }
+
+ if (!initHalFuncTableWithStubs(hal_fn)) {
+ LOG(ERROR) << "Can not initialize the basic function pointer table";
+ return false;
+ }
+
+ if (initfn(hal_fn) != WIFI_SUCCESS) {
+ LOG(ERROR) << "Can not initialize the vendor function pointer table";
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Overall structure of the HAL descriptor XML schema
+ *
+ * <?xml version="1.0" encoding="UTF-8"?>
+ * <WifiVendorHal version="1">
+ * <path>/vendor/lib64/libwifi-hal-qcom.so</path>
+ * <primary>1</primary>
+ * </WifiVendorHal>
+ */
+void WifiLegacyHalFactory::initVendorHalsDescriptorList() {
+ xmlDocPtr xml;
+ xmlNodePtr node, cnode;
+ char* version;
+ std::string path;
+ xmlChar* value;
+ wifi_hal_lib_desc desc;
+
+ LOG(INFO) << "processing vendor HALs descriptions in "
+ << kVendorHalsDescPath;
+ DIR* dirPtr = ::opendir(kVendorHalsDescPath);
+ if (dirPtr == NULL) {
+ LOG(ERROR) << "failed to open " << kVendorHalsDescPath;
+ return;
+ }
+ for (struct dirent* entryPtr = ::readdir(dirPtr); entryPtr != NULL;
+ entryPtr = ::readdir(dirPtr)) {
+ if (isDirectory(entryPtr)) continue;
+
+ if (!isFileExtension(entryPtr->d_name, kVendorHalsDescExt))
+ continue; // only process .xml files
+
+ LOG(INFO) << "processing config file: " << entryPtr->d_name;
+
+ std::string fullPath(kVendorHalsDescPath);
+ fullPath.append("/");
+ fullPath.append(entryPtr->d_name);
+ xml = xmlReadFile(fullPath.c_str(), "UTF-8", XML_PARSE_RECOVER);
+ if (!xml) {
+ LOG(ERROR) << "failed to parse: " << entryPtr->d_name
+ << " skipping...";
+ continue;
+ }
+ node = xmlDocGetRootElement(xml);
+ if (!node) {
+ LOG(ERROR) << "empty config file: " << entryPtr->d_name
+ << " skipping...";
+ goto skip;
+ }
+ if (xmlStrcmp(node->name, BAD_CAST "WifiVendorHal")) {
+ LOG(ERROR) << "bad config, root element not WifiVendorHal: "
+ << entryPtr->d_name << " skipping...";
+ goto skip;
+ }
+ version = (char*)xmlGetProp(node, BAD_CAST "version");
+ if (!version || strtoul(version, NULL, 0) != kVendorHalsDescVersion) {
+ LOG(ERROR) << "conf file: " << entryPtr->d_name
+ << "must have version: " << kVendorHalsDescVersion
+ << ", skipping...";
+ goto skip;
+ }
+ cnode = node->children;
+ path.clear();
+ desc.primary = false;
+ while (cnode) {
+ if (!xmlStrcmp(cnode->name, BAD_CAST "path")) {
+ value = xmlNodeListGetString(xml, cnode->children, 1);
+ if (value) path = (char*)value;
+ xmlFree(value);
+ } else if (!xmlStrcmp(cnode->name, BAD_CAST "primary")) {
+ value = xmlNodeListGetString(xml, cnode->children, 1);
+ desc.primary = !xmlStrcmp(value, BAD_CAST "1");
+ xmlFree(value);
+ }
+ cnode = cnode->next;
+ }
+ if (path.empty()) {
+ LOG(ERROR) << "hal library path not provided in: "
+ << entryPtr->d_name << ", skipping...";
+ goto skip;
+ }
+ if (loadVendorHalLib(path, desc)) {
+ if (desc.primary)
+ descs_.insert(descs_.begin(), desc);
+ else
+ descs_.push_back(desc);
+ }
+ skip:
+ xmlFreeDoc(xml);
+ }
+ ::closedir(dirPtr);
+}
+
+bool WifiLegacyHalFactory::loadVendorHalLib(const std::string& path,
+ wifi_hal_lib_desc& desc) {
+ void* h = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
+ init_wifi_vendor_hal_func_table_t initfn;
+ wifi_error res;
+
+ if (!h) {
+ LOG(ERROR) << "failed to open vendor hal library: " << path;
+ return false;
+ }
+ initfn = (init_wifi_vendor_hal_func_table_t)dlsym(
+ h, "init_wifi_vendor_hal_func_table");
+ if (!initfn) {
+ LOG(ERROR) << "init_wifi_vendor_hal_func_table not found in: " << path;
+ goto out_err;
+ }
+
+ if (!initHalFuncTableWithStubs(&desc.fn)) {
+ LOG(ERROR) << "Can not initialize the basic function pointer table";
+ goto out_err;
+ }
+ res = initfn(&desc.fn);
+ if (res != WIFI_SUCCESS) {
+ LOG(ERROR) << "failed to initialize the vendor func table in: " << path
+ << " error: " << res;
+ goto out_err;
+ }
+
+ res = desc.fn.wifi_early_initialize();
+ // vendor HALs which do not implement early_initialize will return
+ // WIFI_ERROR_NOT_SUPPORTED, treat this as success.
+ if (res != WIFI_SUCCESS && res != WIFI_ERROR_NOT_SUPPORTED) {
+ LOG(ERROR) << "early initialization failed in: " << path
+ << " error: " << res;
+ goto out_err;
+ }
+
+ desc.handle = h;
+ return true;
+out_err:
+ dlclose(h);
+ return false;
+}
+
+} // namespace legacy_hal
+} // namespace implementation
+} // namespace V1_5
+} // namespace wifi
+} // namespace hardware
+} // namespace android
diff --git a/wifi/1.5/default/wifi_legacy_hal_factory.h b/wifi/1.5/default/wifi_legacy_hal_factory.h
new file mode 100644
index 0000000..e3440fa
--- /dev/null
+++ b/wifi/1.5/default/wifi_legacy_hal_factory.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2020 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 WIFI_LEGACY_HAL_FACTORY_H_
+#define WIFI_LEGACY_HAL_FACTORY_H_
+
+#include <wifi_system/interface_tool.h>
+
+#include "wifi_legacy_hal.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_5 {
+namespace implementation {
+// This is in a separate namespace to prevent typename conflicts between
+// the legacy HAL types and the HIDL interface types.
+namespace legacy_hal {
+/**
+ * Class that creates WifiLegacyHal objects for vendor HALs in the system.
+ */
+class WifiLegacyHalFactory {
+ public:
+ WifiLegacyHalFactory(
+ const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
+ virtual ~WifiLegacyHalFactory() = default;
+
+ std::vector<std::shared_ptr<WifiLegacyHal>> getHals();
+
+ private:
+ typedef struct {
+ wifi_hal_fn fn;
+ bool primary;
+ void* handle;
+ } wifi_hal_lib_desc;
+
+ bool initVendorHalDescriptorFromLinked();
+ void initVendorHalsDescriptorList();
+ bool initLinkedHalFunctionTable(wifi_hal_fn* hal_fn);
+ bool loadVendorHalLib(const std::string& path, wifi_hal_lib_desc& desc);
+
+ std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
+ std::vector<wifi_hal_lib_desc> descs_;
+ std::vector<std::shared_ptr<WifiLegacyHal>> legacy_hals_;
+};
+
+} // namespace legacy_hal
+} // namespace implementation
+} // namespace V1_5
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+
+#endif // WIFI_LEGACY_HAL_FACTORY_H_
diff --git a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
index 73b5856..a1122e9 100644
--- a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
@@ -144,6 +144,10 @@
populateStubFor(&hal_fn->wifi_map_dscp_access_category);
populateStubFor(&hal_fn->wifi_reset_dscp_mapping);
populateStubFor(&hal_fn->wifi_set_subsystem_restart_handler);
+ populateStubFor(&hal_fn->wifi_get_supported_iface_name);
+ populateStubFor(&hal_fn->wifi_early_initialize);
+ populateStubFor(&hal_fn->wifi_get_chip_feature_set);
+
return true;
}
} // namespace legacy_hal