Snap for 11510485 from 86a5f18a628b9e1668b8d039bf2697b6dac58230 to 24Q2-release
Change-Id: Ia022372eeab60eb508819df5ac45fc835438dce0
diff --git a/wpa_supplicant/aidl/aidl_manager.cpp b/wpa_supplicant/aidl/aidl_manager.cpp
index d0b3ae2..0daa8ef 100644
--- a/wpa_supplicant/aidl/aidl_manager.cpp
+++ b/wpa_supplicant/aidl/aidl_manager.cpp
@@ -43,15 +43,6 @@
using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
/**
- * Check that the AIDL service is running at least the expected version.
- * Use to avoid the case where the AIDL interface version
- * is greater than the version implemented by the service.
- */
-inline int32_t isAidlServiceVersionAtLeast(int32_t expected_version)
-{
- return expected_version <= aidl_service_version;
-}
-/**
* Check if the provided |wpa_supplicant| structure represents a P2P iface or
* not.
*/
@@ -413,6 +404,16 @@
instance_ = NULL;
}
+/**
+ * Check that the AIDL service is running at least the expected version.
+ * Use to avoid the case where the AIDL interface version
+ * is greater than the version implemented by the service.
+ */
+int32_t AidlManager::isAidlServiceVersionAtLeast(int32_t expected_version)
+{
+ return expected_version <= aidl_service_version;
+}
+
int AidlManager::registerAidlService(struct wpa_global *global)
{
// Create the main aidl service object and register it.
diff --git a/wpa_supplicant/aidl/aidl_manager.h b/wpa_supplicant/aidl/aidl_manager.h
index cd9d5f6..b11a760 100644
--- a/wpa_supplicant/aidl/aidl_manager.h
+++ b/wpa_supplicant/aidl/aidl_manager.h
@@ -171,6 +171,7 @@
enum mlo_info_change_reason reason);
// Methods called from aidl objects.
+ int32_t isAidlServiceVersionAtLeast(int32_t expected_version);
void notifyExtRadioWorkStart(struct wpa_supplicant *wpa_s, uint32_t id);
void notifyExtRadioWorkTimeout(
struct wpa_supplicant *wpa_s, uint32_t id);
diff --git a/wpa_supplicant/aidl/sta_iface.cpp b/wpa_supplicant/aidl/sta_iface.cpp
index bd196c1..a4c2c36 100644
--- a/wpa_supplicant/aidl/sta_iface.cpp
+++ b/wpa_supplicant/aidl/sta_iface.cpp
@@ -2267,9 +2267,73 @@
return 0;
}
+inline bool hasOptQosCharField(QosCharacteristics chars, QosCharacteristics::QosCharacteristicsMask field) {
+ return chars.optionalFieldMask & static_cast<uint32_t>(field);
+}
+
+static int parseQosCharacteristics(struct scs_desc_elem *descElem, QosPolicyScsData qosPolicy) {
+ struct qos_characteristics* suppChars = &descElem->qos_char_elem;
+ if (!qosPolicy.QosCharacteristics) {
+ suppChars->available = false;
+ return 0;
+ }
+
+ QosCharacteristics inputChars = qosPolicy.QosCharacteristics.value();
+ suppChars->available = true;
+
+ if (qosPolicy.direction == QosPolicyScsData::LinkDirection::DOWNLINK) {
+ suppChars->direction = SCS_DIRECTION_DOWN;
+ } else if (qosPolicy.direction == QosPolicyScsData::LinkDirection::UPLINK) {
+ suppChars->direction = SCS_DIRECTION_UP;
+ } else {
+ wpa_printf(MSG_ERROR, "Invalid QoS direction: %d", static_cast<int>(qosPolicy.direction));
+ return -1;
+ }
+
+ // Mandatory fields
+ suppChars->min_si = inputChars.minServiceIntervalUs;
+ suppChars->max_si = inputChars.maxServiceIntervalUs;
+ suppChars->min_data_rate = inputChars.minDataRateKbps;
+ suppChars->delay_bound = inputChars.delayBoundUs;
+
+ // Optional fields
+ uint16_t suppMask = 0;
+ if (hasOptQosCharField(inputChars, QosCharacteristics::QosCharacteristicsMask::MAX_MSDU_SIZE)) {
+ suppMask |= SCS_QOS_BIT_MAX_MSDU_SIZE;
+ suppChars->max_msdu_size = inputChars.maxMsduSizeOctets;
+ }
+ if (hasOptQosCharField(inputChars, QosCharacteristics::QosCharacteristicsMask::SERVICE_START_TIME)) {
+ // Client must provide both the service start time and the link ID if this field exists.
+ suppMask |= SCS_QOS_BIT_SERVICE_START_TIME | SCS_QOS_BIT_SERVICE_START_TIME_LINKID;
+ suppChars->service_start_time = inputChars.serviceStartTimeUs;
+ suppChars->service_start_time_link_id = inputChars.serviceStartTimeLinkId;
+ }
+ if (hasOptQosCharField(inputChars, QosCharacteristics::QosCharacteristicsMask::MEAN_DATA_RATE)) {
+ suppMask |= SCS_QOS_BIT_MEAN_DATA_RATE;
+ suppChars->mean_data_rate = inputChars.meanDataRateKbps;
+ }
+ if (hasOptQosCharField(inputChars, QosCharacteristics::QosCharacteristicsMask::BURST_SIZE)) {
+ suppMask |= SCS_QOS_BIT_DELAYED_BOUNDED_BURST_SIZE;
+ suppChars->burst_size = inputChars.burstSizeOctets;
+ }
+ if (hasOptQosCharField(inputChars, QosCharacteristics::QosCharacteristicsMask::MSDU_LIFETIME)) {
+ suppMask |= SCS_QOS_BIT_MSDU_LIFETIME;
+ suppChars->msdu_lifetime = inputChars.msduLifetimeMs;
+ }
+ if (hasOptQosCharField(inputChars, QosCharacteristics::QosCharacteristicsMask::MSDU_DELIVERY_INFO)) {
+ suppMask |= SCS_QOS_BIT_MSDU_DELIVERY_INFO;
+ // Expects the delivery ratio in the lower 4 bits and the count exponent
+ // in the upper 4 bits. See Figure 9-1001aw in the 802.11be spec.
+ suppChars->msdu_delivery_info = inputChars.msduDeliveryInfo.countExponent << 4
+ | (uint8_t) inputChars.msduDeliveryInfo.deliveryRatio;
+ }
+ suppChars->mask = suppMask;
+ return 0;
+}
+
/**
* This is a request to the AP (if it supports the feature) to apply the QoS policy
- * on traffic in the Downlink.
+ * on traffic in the Downlink or Uplink direction.
*/
std::pair<std::vector<QosPolicyScsRequestStatus>, ndk::ScopedAStatus>
StaIface::addQosPolicyRequestForScsInternal(const std::vector<QosPolicyScsData>& qosPolicyData)
@@ -2288,6 +2352,11 @@
}
free_up_scs_desc(scs_data);
+ // Uplink policies are not supported before AIDL V3.
+ AidlManager *aidl_manager = AidlManager::getInstance();
+ WPA_ASSERT(aidl_manager);
+ bool supportsUplink = aidl_manager->isAidlServiceVersionAtLeast(3);
+
/**
* format:
* [scs_id=<decimal number>] [scs_up=<0-7>]
@@ -2323,39 +2392,49 @@
}
status.qosPolicyScsRequestStatusCode = QosPolicyScsRequestStatusCode::INVALID;
- user_priority = qosPolicyData[i].userPriority;
- if (user_priority < 0 || user_priority > 7) {
- wpa_printf(MSG_ERROR,
- "Intra-Access user priority invalid %d", user_priority);
+ if (parseQosCharacteristics(&desc_elem, qosPolicyData[i])) {
reports.push_back(status);
continue;
}
- desc_elem.intra_access_priority = user_priority;
- desc_elem.scs_up_avail = true;
+ // TCLAS elements only need to be processed for downlink policies.
+ QosPolicyScsData::LinkDirection policyDirection = supportsUplink
+ ? qosPolicyData[i].direction : QosPolicyScsData::LinkDirection::DOWNLINK;
+ if (policyDirection == QosPolicyScsData::LinkDirection::DOWNLINK) {
+ user_priority = qosPolicyData[i].userPriority;
+ if (user_priority < 0 || user_priority > 7) {
+ wpa_printf(MSG_ERROR,
+ "Intra-Access user priority invalid %d", user_priority);
+ reports.push_back(status);
+ continue;
+ }
- /**
- * Supported classifier type 4.
- */
- desc_elem.tclas_elems = (struct tclas_element *) os_malloc(sizeof(struct tclas_element));
- if (!desc_elem.tclas_elems) {
- wpa_printf(MSG_ERROR,
- "Classifier type4 failed with Bad malloc");
- reports.push_back(status);
- continue;
+ desc_elem.intra_access_priority = user_priority;
+ desc_elem.scs_up_avail = true;
+
+ /**
+ * Supported classifier type 4.
+ */
+ desc_elem.tclas_elems = (struct tclas_element *) os_malloc(sizeof(struct tclas_element));
+ if (!desc_elem.tclas_elems) {
+ wpa_printf(MSG_ERROR,
+ "Classifier type4 failed with Bad malloc");
+ reports.push_back(status);
+ continue;
+ }
+
+ elem = desc_elem.tclas_elems;
+ memset(elem, 0, sizeof(struct tclas_element));
+ elem->classifier_type = 4;
+ if (scs_parse_type4(elem, qosPolicyData[i]) < 0) {
+ os_free(elem);
+ reports.push_back(status);
+ continue;
+ }
+
+ desc_elem.num_tclas_elem = 1;
}
- elem = desc_elem.tclas_elems;
- memset(elem, 0, sizeof(struct tclas_element));
- elem->classifier_type = 4;
- if (scs_parse_type4(elem, qosPolicyData[i]) < 0) {
- os_free(elem);
- reports.push_back(status);
- continue;
- }
-
- desc_elem.num_tclas_elem = 1;
-
/* Reallocate memory to scs_desc_elems to accomodate further policies */
new_desc_elems = static_cast<struct scs_desc_elem *>(os_realloc(scs_data->scs_desc_elems,
(num_scs_ids + 1) * sizeof(struct scs_desc_elem)));