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.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