Move downlink-specific QoS processing into
an if-block.

Uplink policies will not have a user priority
or TCLAS elements.

Bug: 319313500
Test: Manual test
       1. Log all fields in the converted object.
       2. Send an uplink and a downlink policy to
          this method.
       3. Verify that the expected fields are processed
          in each case.
Change-Id: I25a02f80c239c165041226c37ec8e051351e9438
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 e4818b5..e3f7532 100644
--- a/wpa_supplicant/aidl/sta_iface.cpp
+++ b/wpa_supplicant/aidl/sta_iface.cpp
@@ -2332,7 +2332,7 @@
 
 /**
  * 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)
@@ -2351,6 +2351,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>]
@@ -2391,39 +2396,44 @@
 			continue;
 		}
 
-		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;
+		// 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;
+			}
+
+			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;
 		}
 
-		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;
-
 		/* 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)));