[WifiCoex] Add WifiChip HIDL APIs for coex
Add HIDL APIs to convey a list of unsafe Wifi channels to the driver for
coex channel avoidance.
Bug: 153651001
Test: build
Change-Id: I8b14f0e2d8855c1f1e363d612617256d8e928f30
diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal
index 2702759..e9caa3d 100644
--- a/wifi/1.5/IWifiChip.hal
+++ b/wifi/1.5/IWifiChip.hal
@@ -17,6 +17,7 @@
package android.hardware.wifi@1.5;
import @1.0::WifiStatus;
+import @1.0::IfaceType;
import @1.5::IWifiApIface;
import @1.0::IWifiIface;
import @1.3::IWifiChip;
@@ -129,7 +130,6 @@
*/
setMultiStaUseCase(MultiStaUseCase useCase) generates (WifiStatus status);
-
/**
* Create bridged IWifiApIface.
*
@@ -167,4 +167,47 @@
*/
removeIfaceInstanceFromBridgedApIface(string brIfaceName, string ifaceInstanceName)
generates (WifiStatus status);
+
+ /**
+ * Representation of a Wi-Fi channel for Wi-Fi coex channel avoidance.
+ */
+ struct CoexUnsafeChannel {
+ /* The band of the channel */
+ WifiBand band;
+ /* The channel number */
+ uint32_t channel;
+ /** The power cap will be a maximum power value in dbm that is allowed to be transmitted by
+ the chip on this channel. A value of PowerCapConstant.NO_POWER_CAP means no limitation
+ on transmitted power is needed by the chip for this channel.
+ */
+ int32_t powerCapDbm;
+ };
+
+ enum PowerCapConstant : int32_t {
+ NO_POWER_CAP = 0x7FFFFFFF,
+ };
+
+ /**
+ * Invoked to indicate that the provided |CoexUnsafeChannels| should be avoided with the
+ * specified restrictions.
+ *
+ * Channel avoidance is a suggestion and should be done on a best-effort approach. If a provided
+ * channel is used, then the specified power cap should be applied.
+ *
+ * In addition, hard restrictions on the Wifi modes may be indicated by |IfaceType| bits
+ * (STA, AP, P2P, NAN, etc) in the |restrictions| bitfield. If a hard restriction is provided,
+ * then the channels should be completely avoided for the provided Wifi modes instead of by
+ * best-effort.
+ *
+ * @param unsafeChannels List of |CoexUnsafeChannels| to avoid.
+ * @param restrictions Bitset of |IfaceType| values indicating Wifi modes to completely avoid.
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+ * |WifiStatusCode.ERROR_INVALID_ARGS|,
+ */
+ setCoexUnsafeChannels(
+ vec<CoexUnsafeChannel> unsafeChannels, bitfield<IfaceType> restrictions)
+ generates (WifiStatus status);
};
diff --git a/wifi/1.5/default/hidl_struct_util.cpp b/wifi/1.5/default/hidl_struct_util.cpp
index 83d06fe..8e2e647 100644
--- a/wifi/1.5/default/hidl_struct_util.cpp
+++ b/wifi/1.5/default/hidl_struct_util.cpp
@@ -2800,6 +2800,47 @@
}
CHECK(false);
}
+
+bool convertHidlCoexUnsafeChannelToLegacy(
+ const IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel,
+ legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel) {
+ if (!legacy_unsafe_channel) {
+ return false;
+ }
+ *legacy_unsafe_channel = {};
+ switch (hidl_unsafe_channel.band) {
+ case WifiBand::BAND_24GHZ:
+ legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_2_4_BAND;
+ break;
+ case WifiBand::BAND_5GHZ:
+ legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_5_0_BAND;
+ break;
+ default:
+ return false;
+ };
+ legacy_unsafe_channel->channel = hidl_unsafe_channel.channel;
+ legacy_unsafe_channel->power_cap_dbm = hidl_unsafe_channel.powerCapDbm;
+ return true;
+}
+
+bool convertHidlVectorOfCoexUnsafeChannelToLegacy(
+ const std::vector<IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels,
+ std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels) {
+ if (!legacy_unsafe_channels) {
+ return false;
+ }
+ *legacy_unsafe_channels = {};
+ for (const auto& hidl_unsafe_channel : hidl_unsafe_channels) {
+ legacy_hal::wifi_coex_unsafe_channel legacy_unsafe_channel;
+ if (!hidl_struct_util::convertHidlCoexUnsafeChannelToLegacy(
+ hidl_unsafe_channel, &legacy_unsafe_channel)) {
+ return false;
+ }
+ legacy_unsafe_channels->push_back(legacy_unsafe_channel);
+ }
+ return true;
+}
+
} // namespace hidl_struct_util
} // namespace implementation
} // namespace V1_5
diff --git a/wifi/1.5/default/hidl_struct_util.h b/wifi/1.5/default/hidl_struct_util.h
index 49d8a12..feb47ef 100644
--- a/wifi/1.5/default/hidl_struct_util.h
+++ b/wifi/1.5/default/hidl_struct_util.h
@@ -71,6 +71,12 @@
IfaceType hidl_interface_type);
legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy(
IWifiChip::MultiStaUseCase use_case);
+bool convertHidlCoexUnsafeChannelToLegacy(
+ const IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel,
+ legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel);
+bool convertHidlVectorOfCoexUnsafeChannelToLegacy(
+ const std::vector<IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels,
+ std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels);
// STA iface conversion methods.
bool convertLegacyFeaturesToHidlStaCapabilities(
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index dd39551..1b0353b 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -722,6 +722,15 @@
hidl_status_cb, use_case);
}
+Return<void> WifiChip::setCoexUnsafeChannels(
+ const hidl_vec<CoexUnsafeChannel>& unsafeChannels,
+ hidl_bitfield<IfaceType> restrictions,
+ setCoexUnsafeChannels_cb hidl_status_cb) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::setCoexUnsafeChannelsInternal,
+ hidl_status_cb, unsafeChannels, restrictions);
+}
+
void WifiChip::invalidateAndRemoveAllIfaces() {
invalidateAndClearBridgedApAll();
invalidateAndClearAll(ap_ifaces_);
@@ -1447,6 +1456,18 @@
return createWifiStatusFromLegacyError(legacy_status);
}
+WifiStatus WifiChip::setCoexUnsafeChannelsInternal(
+ std::vector<CoexUnsafeChannel> unsafe_channels, uint32_t restrictions) {
+ std::vector<legacy_hal::wifi_coex_unsafe_channel> legacy_unsafe_channels;
+ if (!hidl_struct_util::convertHidlVectorOfCoexUnsafeChannelToLegacy(
+ unsafe_channels, &legacy_unsafe_channels)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ auto legacy_status = legacy_hal_.lock()->setCoexUnsafeChannels(
+ legacy_unsafe_channels, restrictions);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
WifiStatus WifiChip::handleChipConfiguration(
/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
ChipModeId mode_id) {
diff --git a/wifi/1.5/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h
index bff8d68..95c122d 100644
--- a/wifi/1.5/default/wifi_chip.h
+++ b/wifi/1.5/default/wifi_chip.h
@@ -174,6 +174,10 @@
Return<void> setMultiStaUseCase(
MultiStaUseCase use_case,
setMultiStaUseCase_cb hidl_status_cb) override;
+ Return<void> setCoexUnsafeChannels(
+ const hidl_vec<CoexUnsafeChannel>& unsafe_channels,
+ hidl_bitfield<IfaceType> restrictions,
+ setCoexUnsafeChannels_cb hidl_status_cb) override;
private:
void invalidateAndRemoveAllIfaces();
@@ -252,6 +256,8 @@
const sp<V1_4::IWifiChipEventCallback>& event_callback);
WifiStatus setMultiStaPrimaryConnectionInternal(const std::string& ifname);
WifiStatus setMultiStaUseCaseInternal(MultiStaUseCase use_case);
+ WifiStatus setCoexUnsafeChannelsInternal(
+ std::vector<CoexUnsafeChannel> unsafe_channels, uint32_t restrictions);
WifiStatus handleChipConfiguration(
std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
diff --git a/wifi/1.5/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp
index 76e718b..773dd9b 100644
--- a/wifi/1.5/default/wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal.cpp
@@ -1521,6 +1521,14 @@
use_case);
}
+wifi_error WifiLegacyHal::setCoexUnsafeChannels(
+ std::vector<wifi_coex_unsafe_channel> unsafe_channels,
+ uint32_t restrictions) {
+ return global_func_table_.wifi_set_coex_unsafe_channels(
+ global_handle_, unsafe_channels.size(), unsafe_channels.data(),
+ restrictions);
+}
+
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 555c540..6266cf6 100644
--- a/wifi/1.5/default/wifi_legacy_hal.h
+++ b/wifi/1.5/default/wifi_legacy_hal.h
@@ -386,6 +386,11 @@
virtual wifi_error multiStaSetPrimaryConnection(const std::string& ifname);
virtual wifi_error multiStaSetUseCase(wifi_multi_sta_use_case use_case);
+ // Coex functions.
+ virtual wifi_error setCoexUnsafeChannels(
+ std::vector<wifi_coex_unsafe_channel> unsafe_channels,
+ uint32_t restrictions);
+
private:
// Retrieve interface handles for all the available interfaces.
wifi_error retrieveIfaceHandles();
diff --git a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
index 71d2ddf..b6c908b 100644
--- a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
@@ -149,6 +149,7 @@
populateStubFor(&hal_fn->wifi_get_chip_feature_set);
populateStubFor(&hal_fn->wifi_multi_sta_set_primary_connection);
populateStubFor(&hal_fn->wifi_multi_sta_set_use_case);
+ populateStubFor(&hal_fn->wifi_set_coex_unsafe_channels);
return true;
}