[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
This commit is contained in:
Quang Luong
2020-11-25 17:52:19 -08:00
parent cb3498d91b
commit 94bcce5ec2
8 changed files with 132 additions and 1 deletions

View File

@@ -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<CoexUnsafeChannel> unsafeChannels, bitfield<IfaceType> restrictions)
generates (WifiStatus status);
};

View File

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

View File

@@ -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<IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels,
std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels);
// STA iface conversion methods.
bool convertLegacyFeaturesToHidlStaCapabilities(

View File

@@ -722,6 +722,15 @@ Return<void> WifiChip::setMultiStaUseCase(
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 @@ WifiStatus WifiChip::setMultiStaUseCaseInternal(MultiStaUseCase use_case) {
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) {

View File

@@ -174,6 +174,10 @@ class WifiChip : public V1_5::IWifiChip {
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 @@ class WifiChip : public V1_5::IWifiChip {
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);

View File

@@ -1521,6 +1521,14 @@ wifi_error WifiLegacyHal::multiStaSetUseCase(wifi_multi_sta_use_case use_case) {
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();

View File

@@ -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<wifi_coex_unsafe_channel> unsafe_channels,
uint32_t restrictions);
private:
// Retrieve interface handles for all the available interfaces.
wifi_error retrieveIfaceHandles();

View File

@@ -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;
}