Wifi: support multiple WIFI chips
The WIFI HAL API has support for multiple WIFI chips
(IWifiChip instances) however the implementation
is hard-coded to support only a single WIFI chip.
This change reworks the implementation so multiple
WIFI chips will be supported.
Support for multiple chips is based on the concept
that each chip is represented by its own vendor HAL
library.
The implementation will look for descriptor
files for vendor HAL libraries under
/vendor/etc/wifi/vendor_hals. It will parse
descriptors, dynamically load vendor HAL libraries
and create WifiLegacyHal and WifiChip objects for
each loaded vendor HAL library.
One of the descriptors should be marked with "primary"
flag. The implementation will create the first WifiChip
object for this library. Typically it is the one
providing the best WIFI functionality, which was
previously used as the only WIFI chip.
Additional support is added inside WifiChip and
WifiLegacyHal for getting available chip modes
and concurrency combinations from the vendor HAL
if available, and allowing the chip to override
network interface name when creating interfaces.
The mechanism for getting chip capabilities is
improved to allow getting chip-global capabilities,
which are independent of any created interfaces.
For example, if the framework needs to start
a SoftAP on the 60GHz band, it needs to find a
chip which supports this band, but before creating
any interface on the chip. The new mechanism allows
this.
Bug: 146922967
Test: atest VtsHalWifiV1_0TargetTest VtsHalWifiNanV1_0TargetTest VtsHalWifiApV1_0TargetTest \
VtsHalWifiV1_1TargetTest \
VtsHalWifiV1_2TargetTest VtsHalWifiNanV1_2TargetTest \
VtsHalWifiV1_3TargetTest \
VtsHalWifiApV1_4TargetTest VtsHalWifiNanV1_4TargetTest VtsHalWifiRttV1_4TargetTest
Change-Id: Ibdff93ea56aff186d4b5361ac77f6f448a0dfd45
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 b898f68..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);
@@ -1599,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;
@@ -1625,7 +1627,8 @@
if (!ifname.empty()) {
return ifname;
}
- return allocateApOrStaIfaceName((isStaApConcurrencyAllowedInCurrentMode() &&
+ return allocateApOrStaIfaceName(IfaceType::AP,
+ (isStaApConcurrencyAllowedInCurrentMode() &&
!isDualApAllowedInCurrentMode())
? 1
: 0);
@@ -1634,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() {
@@ -1670,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