wifi: Get the supported radio combinations matrix

Added API to get the supported radio combinations
of the chip. This is mainly to check if the chip is
capable of multi band simultaneous operation.

For Example in case of a chip which has two radios, where one radio is
capable of 2.4GHz 2X2 only and another radio which is capable of either
5GHz or 6GHz 2X2, number of possible radio combinations in this case
are 5 and possible combinations are:
    {{{2G 2X2}}, //Standalone 2G
    {{5G 2X2}}, //Standalone 5G
    {{6G 2X2}}, //Standalone 6G
    {{2G 2X2}, {5G 2X2}}, //2G+5G DBS
    {{2G 2X2}, {6G 2X2}}} //2G+6G DBS

Bug: 208877624
Test: vts test
Change-Id: I4c90f80002ca138133a575bca80dfdef2a593ab2
This commit is contained in:
Sunil Ravi
2022-01-24 10:39:56 -08:00
parent 1aab61da7b
commit ef97d23f88
10 changed files with 338 additions and 0 deletions

View File

@@ -99,4 +99,35 @@ interface IWifiChip extends @1.5::IWifiChip {
getUsableChannels_1_6(WifiBand band, bitfield<WifiIfaceMode> ifaceModeMask,
bitfield<UsableChannelFilter> filterMask)
generates (WifiStatus status, vec<WifiUsableChannel> channels);
/**
* Retrieve the list of all the possible radio combinations supported by this
* chip.
*
* @return status WifiStatus of the operation.
* Possible status codes:
* |WifiStatusCode.SUCCESS|,
* |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
* |WifiStatusCode.ERROR_NOT_SUPPORTED|,
* |WifiStatusCode.FAILURE_UNKNOWN|
* @return radioCombinationMatrix
* A list of all the possible radio combinations represented by
* |WifiRadioCombinationMatrix|.
* For Example in case of a chip which has two radios, where one radio is
* capable of 2.4GHz 2X2 only and another radio which is capable of either
* 5GHz or 6GHz 2X2, number of possible radio combinations in this case
* are 5 and possible combinations are
* {{{2G 2X2}}, //Standalone 2G
* {{5G 2X2}}, //Standalone 5G
* {{6G 2X2}}, //Standalone 6G
* {{2G 2X2}, {5G 2X2}}, //2G+5G DBS
* {{2G 2X2}, {6G 2X2}}} //2G+6G DBS
* Note: Since this chip doesnt support 5G+6G simultaneous operation
* as there is only one radio which can support both bands, So it can only
* do MCC 5G+6G. This table should not get populated with possible MCC
* configurations. This is only for simultaneous radio configurations
* (such as standalone, multi band simultaneous or single band simultaneous).
*/
getSupportedRadioCombinationsMatrix()
generates (WifiStatus status, WifiRadioCombinationMatrix radioCombinationMatrix);
};

View File

@@ -367,6 +367,21 @@ uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand hidl_band) {
}
}
V1_5::WifiBand convertLegacyMacBandToHidlWifiBand(uint32_t band) {
switch (band) {
case legacy_hal::WLAN_MAC_2_4_BAND:
return V1_5::WifiBand::BAND_24GHZ;
case legacy_hal::WLAN_MAC_5_0_BAND:
return V1_5::WifiBand::BAND_5GHZ;
case legacy_hal::WLAN_MAC_6_0_BAND:
return V1_5::WifiBand::BAND_6GHZ;
case legacy_hal::WLAN_MAC_60_0_BAND:
return V1_5::WifiBand::BAND_60GHZ;
default:
return V1_5::WifiBand::BAND_UNSPECIFIED;
}
}
uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask) {
uint32_t legacy_iface_mask = 0;
if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_STA) {
@@ -2905,6 +2920,85 @@ bool convertHidlVectorOfCoexUnsafeChannelToLegacy(
return true;
}
V1_6::WifiAntennaMode convertLegacyAntennaConfigurationToHidl(uint32_t antenna_cfg) {
switch (antenna_cfg) {
case legacy_hal::WIFI_ANTENNA_1X1:
return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_1X1;
case legacy_hal::WIFI_ANTENNA_2X2:
return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_2X2;
case legacy_hal::WIFI_ANTENNA_3X3:
return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_3X3;
case legacy_hal::WIFI_ANTENNA_4X4:
return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_4X4;
default:
return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_UNSPECIFIED;
}
}
bool convertLegacyWifiRadioConfigurationToHidl(
legacy_hal::wifi_radio_configuration* radio_configuration,
V1_6::WifiRadioConfiguration* hidl_radio_configuration) {
if (!hidl_radio_configuration) {
return false;
}
*hidl_radio_configuration = {};
hidl_radio_configuration->bandInfo =
hidl_struct_util::convertLegacyMacBandToHidlWifiBand(radio_configuration->band);
if (hidl_radio_configuration->bandInfo == V1_5::WifiBand::BAND_UNSPECIFIED) {
LOG(ERROR) << "Unspecified band";
return false;
}
hidl_radio_configuration->antennaMode =
hidl_struct_util::convertLegacyAntennaConfigurationToHidl(
radio_configuration->antenna_cfg);
return true;
}
bool convertLegacyRadioCombinationsMatrixToHidl(
legacy_hal::wifi_radio_combination_matrix* legacy_matrix,
WifiRadioCombinationMatrix* hidl_matrix) {
if (!hidl_matrix || !legacy_matrix) {
return false;
}
*hidl_matrix = {};
int num_combinations = legacy_matrix->num_radio_combinations;
std::vector<V1_6::WifiRadioCombination> radio_combinations_vec;
if (!num_combinations) {
LOG(ERROR) << "zero radio combinations";
return false;
}
wifi_radio_combination* l_radio_combinations_ptr = legacy_matrix->radio_combinations;
for (int i = 0; i < num_combinations; i++) {
int num_configurations = l_radio_combinations_ptr->num_radio_configurations;
WifiRadioCombination radioCombination;
std::vector<V1_6::WifiRadioConfiguration> radio_configurations_vec;
if (!num_configurations) {
LOG(ERROR) << "zero radio configurations";
return false;
}
for (int j = 0; j < num_configurations; j++) {
WifiRadioConfiguration radioConfiguration;
wifi_radio_configuration* l_radio_configurations_ptr =
&l_radio_combinations_ptr->radio_configurations[j];
if (!hidl_struct_util::convertLegacyWifiRadioConfigurationToHidl(
l_radio_configurations_ptr, &radioConfiguration)) {
LOG(ERROR) << "Error converting wifi radio configuration";
return false;
}
radio_configurations_vec.push_back(radioConfiguration);
}
radioCombination.radioConfigurations = radio_configurations_vec;
radio_combinations_vec.push_back(radioCombination);
l_radio_combinations_ptr =
(wifi_radio_combination*)((u8*)l_radio_combinations_ptr +
sizeof(wifi_radio_combination) +
(sizeof(wifi_radio_configuration) * num_configurations));
}
hidl_matrix->radioCombinations = radio_combinations_vec;
return true;
}
} // namespace hidl_struct_util
} // namespace implementation
} // namespace V1_6

View File

@@ -74,6 +74,11 @@ bool convertHidlCoexUnsafeChannelToLegacy(
bool convertHidlVectorOfCoexUnsafeChannelToLegacy(
const std::vector<V1_5::IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels,
std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels);
bool convertLegacyRadioCombinationsMatrixToHidl(
legacy_hal::wifi_radio_combination_matrix* legacy_matrix,
V1_6::WifiRadioCombinationMatrix* hidl_matrix);
V1_5::WifiBand convertLegacyMacBandToHidlWifiBand(uint32_t band);
V1_6::WifiAntennaMode convertLegacyAntennaConfigurationToHidl(uint32_t antenna_cfg);
// STA iface conversion methods.
bool convertLegacyFeaturesToHidlStaCapabilities(uint64_t legacy_feature_set,

View File

@@ -377,6 +377,108 @@ TEST_F(HidlStructUtilTest, CanConvertLegacyFeaturesToHidl) {
HidlChipCaps::SET_LATENCY_MODE | HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP,
hidle_caps);
}
void insertRadioCombination(legacy_hal::wifi_radio_combination* dst_radio_combination_ptr,
int num_radio_configurations,
legacy_hal::wifi_radio_configuration* radio_configuration) {
dst_radio_combination_ptr->num_radio_configurations = num_radio_configurations;
memcpy(dst_radio_combination_ptr->radio_configurations, radio_configuration,
num_radio_configurations * sizeof(legacy_hal::wifi_radio_configuration));
}
void verifyRadioCombination(WifiRadioCombination* radioCombination, size_t num_radio_configurations,
legacy_hal::wifi_radio_configuration* radio_configuration) {
EXPECT_EQ(num_radio_configurations, radioCombination->radioConfigurations.size());
for (size_t i = 0; i < num_radio_configurations; i++) {
EXPECT_EQ(hidl_struct_util::convertLegacyMacBandToHidlWifiBand(radio_configuration->band),
radioCombination->radioConfigurations[i].bandInfo);
EXPECT_EQ(hidl_struct_util::convertLegacyAntennaConfigurationToHidl(
radio_configuration->antenna_cfg),
radioCombination->radioConfigurations[i].antennaMode);
radio_configuration++;
}
}
TEST_F(HidlStructUtilTest, canConvertLegacyRadioCombinationsMatrixToHidl) {
legacy_hal::wifi_radio_configuration radio_configurations_array1[] = {
{.band = legacy_hal::WLAN_MAC_2_4_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_1X1},
};
legacy_hal::wifi_radio_configuration radio_configurations_array2[] = {
{.band = legacy_hal::WLAN_MAC_2_4_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_2X2},
{.band = legacy_hal::WLAN_MAC_5_0_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_3X3},
};
legacy_hal::wifi_radio_configuration radio_configurations_array3[] = {
{.band = legacy_hal::WLAN_MAC_2_4_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_2X2},
{.band = legacy_hal::WLAN_MAC_6_0_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_1X1},
{.band = legacy_hal::WLAN_MAC_5_0_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_4X4},
};
int num_radio_configs = 0;
int num_combinations = 0;
std::array<char, 256> buffer;
buffer.fill(0);
legacy_hal::wifi_radio_combination_matrix* legacy_matrix =
reinterpret_cast<wifi_radio_combination_matrix*>(buffer.data());
legacy_hal::wifi_radio_combination* radio_combinations;
// Prepare a legacy wifi_radio_combination_matrix
legacy_matrix->num_radio_combinations = 3;
// Insert first combination
radio_combinations =
(legacy_hal::wifi_radio_combination*)((char*)legacy_matrix->radio_combinations);
insertRadioCombination(
radio_combinations,
sizeof(radio_configurations_array1) / sizeof(radio_configurations_array1[0]),
radio_configurations_array1);
num_combinations++;
num_radio_configs +=
sizeof(radio_configurations_array1) / sizeof(radio_configurations_array1[0]);
// Insert second combination
radio_combinations =
(legacy_hal::wifi_radio_combination*)((char*)legacy_matrix->radio_combinations +
(num_combinations *
sizeof(legacy_hal::wifi_radio_combination)) +
(num_radio_configs *
sizeof(wifi_radio_configuration)));
insertRadioCombination(
radio_combinations,
sizeof(radio_configurations_array2) / sizeof(radio_configurations_array2[0]),
radio_configurations_array2);
num_combinations++;
num_radio_configs +=
sizeof(radio_configurations_array2) / sizeof(radio_configurations_array2[0]);
// Insert third combination
radio_combinations =
(legacy_hal::wifi_radio_combination*)((char*)legacy_matrix->radio_combinations +
(num_combinations *
sizeof(legacy_hal::wifi_radio_combination)) +
(num_radio_configs *
sizeof(wifi_radio_configuration)));
insertRadioCombination(
radio_combinations,
sizeof(radio_configurations_array3) / sizeof(radio_configurations_array3[0]),
radio_configurations_array3);
V1_6::WifiRadioCombinationMatrix converted_matrix{};
hidl_struct_util::convertLegacyRadioCombinationsMatrixToHidl(legacy_matrix, &converted_matrix);
// Verify the conversion
EXPECT_EQ(legacy_matrix->num_radio_combinations, converted_matrix.radioCombinations.size());
verifyRadioCombination(
&converted_matrix.radioCombinations[0],
sizeof(radio_configurations_array1) / sizeof(radio_configurations_array1[0]),
radio_configurations_array1);
verifyRadioCombination(
&converted_matrix.radioCombinations[1],
sizeof(radio_configurations_array2) / sizeof(radio_configurations_array2[0]),
radio_configurations_array2);
verifyRadioCombination(
&converted_matrix.radioCombinations[2],
sizeof(radio_configurations_array3) / sizeof(radio_configurations_array3[0]),
radio_configurations_array3);
}
} // namespace implementation
} // namespace V1_6
} // namespace wifi

View File

@@ -722,6 +722,12 @@ Return<void> WifiChip::getUsableChannels_1_6(
filterMask);
}
Return<void> WifiChip::getSupportedRadioCombinationsMatrix(
getSupportedRadioCombinationsMatrix_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::getSupportedRadioCombinationsMatrixInternal, hidl_status_cb);
}
void WifiChip::invalidateAndRemoveAllIfaces() {
invalidateAndClearBridgedApAll();
invalidateAndClearAll(ap_ifaces_);
@@ -1461,6 +1467,28 @@ std::pair<WifiStatus, std::vector<V1_6::WifiUsableChannel>> WifiChip::getUsableC
return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_usable_channels};
}
std::pair<WifiStatus, V1_6::WifiRadioCombinationMatrix>
WifiChip::getSupportedRadioCombinationsMatrixInternal() {
legacy_hal::wifi_error legacy_status;
legacy_hal::wifi_radio_combination_matrix* legacy_matrix;
std::tie(legacy_status, legacy_matrix) =
legacy_hal_.lock()->getSupportedRadioCombinationsMatrix();
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
LOG(ERROR) << "Failed to get SupportedRadioCombinations matrix from legacy HAL: "
<< legacyErrorToString(legacy_status);
return {createWifiStatusFromLegacyError(legacy_status), {}};
}
V1_6::WifiRadioCombinationMatrix hidl_matrix;
if (!hidl_struct_util::convertLegacyRadioCombinationsMatrixToHidl(legacy_matrix,
&hidl_matrix)) {
LOG(ERROR) << "Failed convertLegacyRadioCombinationsMatrixToHidl() ";
return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), {}};
}
return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_matrix};
}
WifiStatus WifiChip::handleChipConfiguration(
/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id) {
// If the chip is already configured in a different mode, stop

View File

@@ -160,6 +160,8 @@ class WifiChip : public V1_6::IWifiChip {
hidl_bitfield<V1_5::WifiIfaceMode> ifaceModeMask,
hidl_bitfield<UsableChannelFilter> filterMask,
getUsableChannels_1_6_cb _hidl_cb) override;
Return<void> getSupportedRadioCombinationsMatrix(
getSupportedRadioCombinationsMatrix_cb hidl_status_cb) override;
private:
void invalidateAndRemoveAllIfaces();
@@ -267,6 +269,7 @@ class WifiChip : public V1_6::IWifiChip {
const sp<IWifiIface>& bound_iface);
std::pair<WifiStatus, std::vector<V1_6::WifiUsableChannel>> getUsableChannelsInternal_1_6(
WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask);
std::pair<WifiStatus, WifiRadioCombinationMatrix> getSupportedRadioCombinationsMatrixInternal();
ChipId chip_id_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;

View File

@@ -37,6 +37,7 @@ static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
static constexpr uint32_t kMaxRingBuffers = 10;
static constexpr uint32_t kMaxWifiUsableChannels = 256;
static constexpr uint32_t kMaxSupportedRadioCombinationsMatrixLength = 256;
// need a long timeout (1000ms) for chips that unload their driver.
static constexpr uint32_t kMaxStopCompleteWaitMs = 1000;
static constexpr char kDriverPropName[] = "wlan.driver.status";
@@ -1537,6 +1538,19 @@ wifi_error WifiLegacyHal::setIndoorState(bool isIndoor) {
return global_func_table_.wifi_set_indoor_state(global_handle_, isIndoor);
}
std::pair<wifi_error, wifi_radio_combination_matrix*>
WifiLegacyHal::getSupportedRadioCombinationsMatrix() {
std::array<char, kMaxSupportedRadioCombinationsMatrixLength> buffer;
buffer.fill(0);
uint32_t size = 0;
wifi_radio_combination_matrix* radio_combination_matrix_ptr =
reinterpret_cast<wifi_radio_combination_matrix*>(buffer.data());
wifi_error status = global_func_table_.wifi_get_supported_radio_combinations_matrix(
global_handle_, buffer.size(), &size, radio_combination_matrix_ptr);
CHECK(size >= 0 && size <= kMaxSupportedRadioCombinationsMatrixLength);
return {status, radio_combination_matrix_ptr};
}
void WifiLegacyHal::invalidate() {
global_handle_ = nullptr;
iface_name_to_handle_.clear();

View File

@@ -204,6 +204,11 @@ using ::WIFI_AC_BE;
using ::WIFI_AC_BK;
using ::WIFI_AC_VI;
using ::WIFI_AC_VO;
using ::WIFI_ANTENNA_1X1;
using ::WIFI_ANTENNA_2X2;
using ::WIFI_ANTENNA_3X3;
using ::WIFI_ANTENNA_4X4;
using ::WIFI_ANTENNA_UNSPECIFIED;
using ::wifi_band;
using ::WIFI_BAND_A;
using ::WIFI_BAND_A_DFS;
@@ -281,6 +286,9 @@ using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON;
using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF;
using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON;
using ::WIFI_POWER_SCENARIO_VOICE_CALL;
using ::wifi_radio_combination;
using ::wifi_radio_combination_matrix;
using ::wifi_radio_configuration;
using ::wifi_rate;
using ::wifi_request_id;
using ::wifi_ring_buffer_status;
@@ -660,6 +668,8 @@ class WifiLegacyHal {
wifi_error setIndoorState(bool isIndoor);
std::pair<wifi_error, wifi_radio_combination_matrix*> getSupportedRadioCombinationsMatrix();
private:
// Retrieve interface handles for all the available interfaces.
wifi_error retrieveIfaceHandles();

View File

@@ -162,6 +162,7 @@ bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) {
populateStubFor(&hal_fn->wifi_get_usable_channels);
populateStubFor(&hal_fn->wifi_trigger_subsystem_restart);
populateStubFor(&hal_fn->wifi_set_indoor_state);
populateStubFor(&hal_fn->wifi_get_supported_radio_combinations_matrix);
return true;
}
} // namespace legacy_hal

View File

@@ -46,6 +46,7 @@ import @1.0::WifiRateNss;
import @1.4::RttPreamble;
import @1.4::WifiRatePreamble;
import @1.5::NanConfigRequestSupplemental;
import @1.5::WifiBand;
import @1.5::StaLinkLayerIfaceContentionTimeStats;
import @1.5::WifiIfaceMode;
@@ -86,6 +87,17 @@ enum WifiRatePreamble : @1.4::WifiRatePreamble {
EHT = 6,
};
/**
* Antenna configuration
*/
enum WifiAntennaMode : uint32_t {
WIFI_ANTENNA_MODE_UNSPECIFIED = 0,
WIFI_ANTENNA_MODE_1X1 = 1,
WIFI_ANTENNA_MODE_2X2 = 2,
WIFI_ANTENNA_MODE_3X3 = 3,
WIFI_ANTENNA_MODE_4X4 = 4,
};
/**
* Channel information.
*/
@@ -1262,3 +1274,41 @@ struct NanCapabilities {
*/
bool instantCommunicationModeSupportFlag;
};
/**
* Wifi radio configuration
*/
struct WifiRadioConfiguration {
/**
* Band on which this radio chain is operating.
* Valid values of bandInfo are: BAND_24GHZ, BAND_5GHZ, BAND_6GHZ and
* BAND_60GHZ.
*
*/
WifiBand bandInfo;
/**
* Wifi Antenna configuration.
*/
WifiAntennaMode antennaMode;
};
/**
* Wifi radio combination
*/
struct WifiRadioCombination {
/**
* A list of radio configurations in this combination.
*/
vec<WifiRadioConfiguration> radioConfigurations;
};
/**
* Wifi radio combinations matrix retrieved via |getSupportedRadioCombinationsMatrix|.
*/
struct WifiRadioCombinationMatrix {
/**
* A list of all the possible radio combinations that the chip can operate.
*/
vec<WifiRadioCombination> radioCombinations;
};