From 94bcce5ec248994af5c74c0df256e8a4dfd94a84 Mon Sep 17 00:00:00 2001 From: Quang Luong Date: Wed, 25 Nov 2020 17:52:19 -0800 Subject: [PATCH] [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 --- wifi/1.5/IWifiChip.hal | 45 +++++++++++++++++++++- wifi/1.5/default/hidl_struct_util.cpp | 41 ++++++++++++++++++++ wifi/1.5/default/hidl_struct_util.h | 6 +++ wifi/1.5/default/wifi_chip.cpp | 21 ++++++++++ wifi/1.5/default/wifi_chip.h | 6 +++ wifi/1.5/default/wifi_legacy_hal.cpp | 8 ++++ wifi/1.5/default/wifi_legacy_hal.h | 5 +++ wifi/1.5/default/wifi_legacy_hal_stubs.cpp | 1 + 8 files changed, 132 insertions(+), 1 deletion(-) diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal index 2702759c41..e9caa3deb5 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 @@ interface IWifiChip extends @1.4::IWifiChip { */ setMultiStaUseCase(MultiStaUseCase useCase) generates (WifiStatus status); - /** * Create bridged IWifiApIface. * @@ -167,4 +167,47 @@ interface IWifiChip extends @1.4::IWifiChip { */ 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 unsafeChannels, bitfield 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 83d06fe398..8e2e647cc5 100644 --- a/wifi/1.5/default/hidl_struct_util.cpp +++ b/wifi/1.5/default/hidl_struct_util.cpp @@ -2800,6 +2800,47 @@ legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy( } 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& hidl_unsafe_channels, + std::vector* 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 49d8a1213e..feb47ef7ab 100644 --- a/wifi/1.5/default/hidl_struct_util.h +++ b/wifi/1.5/default/hidl_struct_util.h @@ -71,6 +71,12 @@ legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy( 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& hidl_unsafe_channels, + std::vector* 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 dd39551571..1b0353b353 100644 --- a/wifi/1.5/default/wifi_chip.cpp +++ b/wifi/1.5/default/wifi_chip.cpp @@ -722,6 +722,15 @@ Return WifiChip::setMultiStaUseCase( hidl_status_cb, use_case); } +Return WifiChip::setCoexUnsafeChannels( + const hidl_vec& unsafeChannels, + hidl_bitfield 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 @@ WifiStatus WifiChip::setMultiStaUseCaseInternal(MultiStaUseCase use_case) { return createWifiStatusFromLegacyError(legacy_status); } +WifiStatus WifiChip::setCoexUnsafeChannelsInternal( + std::vector unsafe_channels, uint32_t restrictions) { + std::vector 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* lock, ChipModeId mode_id) { diff --git a/wifi/1.5/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h index bff8d680a3..95c122d2b1 100644 --- a/wifi/1.5/default/wifi_chip.h +++ b/wifi/1.5/default/wifi_chip.h @@ -174,6 +174,10 @@ class WifiChip : public V1_5::IWifiChip { Return setMultiStaUseCase( MultiStaUseCase use_case, setMultiStaUseCase_cb hidl_status_cb) override; + Return setCoexUnsafeChannels( + const hidl_vec& unsafe_channels, + hidl_bitfield restrictions, + setCoexUnsafeChannels_cb hidl_status_cb) override; private: void invalidateAndRemoveAllIfaces(); @@ -252,6 +256,8 @@ class WifiChip : public V1_5::IWifiChip { const sp& event_callback); WifiStatus setMultiStaPrimaryConnectionInternal(const std::string& ifname); WifiStatus setMultiStaUseCaseInternal(MultiStaUseCase use_case); + WifiStatus setCoexUnsafeChannelsInternal( + std::vector unsafe_channels, uint32_t restrictions); WifiStatus handleChipConfiguration( std::unique_lock* 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 76e718b74a..773dd9b4f3 100644 --- a/wifi/1.5/default/wifi_legacy_hal.cpp +++ b/wifi/1.5/default/wifi_legacy_hal.cpp @@ -1521,6 +1521,14 @@ wifi_error WifiLegacyHal::multiStaSetUseCase(wifi_multi_sta_use_case use_case) { use_case); } +wifi_error WifiLegacyHal::setCoexUnsafeChannels( + std::vector 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 555c540102..6266cf6fd5 100644 --- a/wifi/1.5/default/wifi_legacy_hal.h +++ b/wifi/1.5/default/wifi_legacy_hal.h @@ -386,6 +386,11 @@ class WifiLegacyHal { 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 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 71d2ddf688..b6c908b0d2 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 @@ bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) { 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; }