Merge "wifi: Refactoring code for IfaceParams extendation"
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 3a99bb6..09b8a6d 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -68,6 +68,10 @@
 L_CFLAGS += -DCONFIG_NO_ROAMING
 endif
 
+ifeq ($(WIFI_PRIV_CMD_UPDATE_MBO_CELL_STATUS), enabled)
+L_CFLAGS += -DENABLE_PRIV_CMD_UPDATE_MBO_CELL_STATUS
+endif
+
 # Use Android specific directory for control interface sockets
 L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/vendor/wifi/wpa/sockets\"
 L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/vendor/wifi/wpa/sockets\"
diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config
index 5f8c8f6..b11e371 100644
--- a/wpa_supplicant/android.config
+++ b/wpa_supplicant/android.config
@@ -556,4 +556,7 @@
 # be completely removed in a future release.
 CONFIG_WEP=y
 
+# WPA3-Personal (SAE) PK (Public Key) mode
+CONFIG_SAE_PK=y
+
 include $(wildcard $(LOCAL_PATH)/android_config_*.inc)
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 8a8765b..0d5b285 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -4328,6 +4328,7 @@
 	config->disassoc_imminent_rssi_threshold =
 		DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD;
 	config->oce = DEFAULT_OCE_SUPPORT;
+	config->btm_offload = DEFAULT_BTM_OFFLOAD;
 #endif /* CONFIG_MBO */
 
 	if (ctrl_interface)
@@ -5111,6 +5112,7 @@
 		    MBO_CELL_CAPA_NOT_SUPPORTED), 0 },
 	{ INT_RANGE(disassoc_imminent_rssi_threshold, -120, 0), 0 },
 	{ INT_RANGE(oce, 0, 3), 0 },
+	{ INT_RANGE(btm_offload, 0, 1), CFG_CHANGED_DISABLE_BTM_NOTIFY },
 #endif /* CONFIG_MBO */
 	{ INT(gas_address3), 0 },
 	{ INT_RANGE(ftm_responder, 0, 1), 0 },
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 0b9e3db..868a8b3 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -45,6 +45,7 @@
 #define DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD -75
 #define DEFAULT_OCE_SUPPORT OCE_STA
 #define DEFAULT_EXTENDED_KEY_ID 0
+#define DEFAULT_BTM_OFFLOAD 0
 
 #include "config_ssid.h"
 #include "wps/wps.h"
@@ -377,6 +378,7 @@
 #define CFG_CHANGED_WOWLAN_TRIGGERS BIT(18)
 #define CFG_CHANGED_DISABLE_BTM BIT(19)
 #define CFG_CHANGED_BGSCAN BIT(20)
+#define CFG_CHANGED_DISABLE_BTM_NOTIFY BIT(21)
 
 /**
  * struct wpa_config - wpa_supplicant configuration data
@@ -1451,6 +1453,14 @@
 	 *  - Set BIT(1) to enable OCE in STA-CFON mode
 	 */
 	unsigned int oce;
+
+	/**
+	 * btm_offload - Set where to perform roaming logic
+	 *  - Set to 0 to handle fully roaming logic in supplicant
+	 *  - Set to 1 to skip roaming logic in supplicant for firmware roaming
+	 *    just parse BTM frame and notify framework
+	 */
+        int btm_offload;
 #endif /* CONFIG_MBO */
 
 	/**
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.cpp b/wpa_supplicant/hidl/1.4/sta_iface.cpp
index 47a75ad..7aa5ebf 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_iface.cpp
@@ -692,6 +692,14 @@
 	    &StaIface::getWpaDriverCapabilitiesInternal, _hidl_cb);
 }
 
+Return<void> StaIface::getWpaDriverCapabilities_1_4(
+		getWpaDriverCapabilities_1_4_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_UNKNOWN,
+	    &StaIface::getWpaDriverCapabilitiesInternal_1_4, _hidl_cb);
+}
+
 Return<void> StaIface::setMboCellularDataStatus(bool available,
 		setMboCellularDataStatus_cb _hidl_cb)
 {
@@ -1535,6 +1543,12 @@
 std::pair<SupplicantStatus, uint32_t>
 StaIface::getWpaDriverCapabilitiesInternal()
 {
+	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"}, 0};
+}
+
+std::pair<V1_4::SupplicantStatus, uint32_t>
+StaIface::getWpaDriverCapabilitiesInternal_1_4()
+{
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	uint32_t mask = 0;
 
@@ -1548,10 +1562,13 @@
 		mask |= V1_3::WpaDriverCapabilitiesMask::OCE;
 	}
 #endif
+#ifdef CONFIG_SAE_PK
+	mask |= V1_4::WpaDriverCapabilitiesMask::SAE_PK;
+#endif
 
 	wpa_printf(MSG_DEBUG, "Driver capability mask: 0x%x", mask);
 
-	return {{SupplicantStatusCode::SUCCESS, ""}, mask};
+	return {{V1_4::SupplicantStatusCode::SUCCESS, ""}, mask};
 }
 
 SupplicantStatus StaIface::setMboCellularDataStatusInternal(bool available)
@@ -1565,7 +1582,19 @@
 	} else {
 		mbo_cell_capa = MBO_CELL_CAPA_NOT_AVAILABLE;
 	}
+
+#ifdef ENABLE_PRIV_CMD_UPDATE_MBO_CELL_STATUS
+	char mbo_cmd[32];
+	char buf[32];
+
+	os_snprintf(mbo_cmd, sizeof(mbo_cmd), "%s %d", "MBO CELL_DATA_CAP", mbo_cell_capa);
+	if (wpa_drv_driver_cmd(wpa_s, mbo_cmd, buf, sizeof(buf)) < 0) {
+		wpa_printf(MSG_ERROR, "MBO CELL_DATA_CAP cmd failed CAP:%d", mbo_cell_capa);
+	}
+#else
 	wpas_mbo_update_cell_capa(wpa_s, mbo_cell_capa);
+#endif
+
 	return {SupplicantStatusCode::SUCCESS, ""};
 #else
 	return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.h b/wpa_supplicant/hidl/1.4/sta_iface.h
index 26a26d7..bb5344b 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.h
+++ b/wpa_supplicant/hidl/1.4/sta_iface.h
@@ -203,6 +203,8 @@
 	    setMboCellularDataStatus_cb _hidl_cb) override;
 	Return<void> getKeyMgmtCapabilities_1_3(
 	    getKeyMgmtCapabilities_1_3_cb _hidl_cb) override;
+	Return<void> getWpaDriverCapabilities_1_4(
+	    getWpaDriverCapabilities_1_4_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -300,6 +302,7 @@
 	std::pair<SupplicantStatus, uint32_t> getWpaDriverCapabilitiesInternal();
 	SupplicantStatus setMboCellularDataStatusInternal(bool available);
 	std::pair<SupplicantStatus, uint32_t> getKeyMgmtCapabilitiesInternal_1_3();
+	std::pair<V1_4::SupplicantStatus, uint32_t> getWpaDriverCapabilitiesInternal_1_4();
 
 	struct wpa_supplicant* retrieveIfacePtr();
 
diff --git a/wpa_supplicant/hidl/1.4/sta_network.cpp b/wpa_supplicant/hidl/1.4/sta_network.cpp
index d62fdae..6d53282 100644
--- a/wpa_supplicant/hidl/1.4/sta_network.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_network.cpp
@@ -997,6 +997,13 @@
 	    &StaNetwork::enableSaeH2eOnlyModeInternal, _hidl_cb, enable);
 }
 
+Return<void> StaNetwork::enableSaePkOnlyMode(bool enable, enableSaePkOnlyMode_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &StaNetwork::enableSaePkOnlyModeInternal, _hidl_cb, enable);
+}
+
 std::pair<SupplicantStatus, uint32_t> StaNetwork::getIdInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, network_id_};
@@ -2616,6 +2623,18 @@
 	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
 }
 
+V1_4::SupplicantStatus StaNetwork::enableSaePkOnlyModeInternal(bool enable)
+{
+#ifdef CONFIG_SAE_PK
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	wpa_ssid->sae_pk = enable ? SAE_PK_MODE_ONLY : SAE_PK_MODE_AUTOMATIC;
+	resetInternalStateAfterParamsUpdate();
+	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+#else
+	return {V1_4::SupplicantStatusCode::FAILURE_UNSUPPORTED, ""};
+#endif
+}
+
 }  // namespace implementation
 }  // namespace V1_4
 }  // namespace supplicant
diff --git a/wpa_supplicant/hidl/1.4/sta_network.h b/wpa_supplicant/hidl/1.4/sta_network.h
index b00f8e5..48bf77b 100644
--- a/wpa_supplicant/hidl/1.4/sta_network.h
+++ b/wpa_supplicant/hidl/1.4/sta_network.h
@@ -272,6 +272,7 @@
 	Return<void> getGroupCipher_1_4(
 	    getGroupCipher_1_4_cb _hidl_cb) override;
 	Return<void> enableSaeH2eOnlyMode(bool enable, enableSaeH2eOnlyMode_cb _hidl_cb) override;
+	Return<void> enableSaePkOnlyMode(bool enable, enableSaePkOnlyMode_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -414,6 +415,7 @@
 	V1_4::SupplicantStatus setPairwiseCipher_1_4Internal(
 	    uint32_t pairwise_cipher_mask);
 	V1_4::SupplicantStatus enableSaeH2eOnlyModeInternal(bool enable);
+	V1_4::SupplicantStatus enableSaePkOnlyModeInternal(bool enable);
 
 	struct wpa_ssid* retrieveNetworkPtr();
 	struct wpa_supplicant* retrieveIfacePtr();
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index c706a4e..6996b09 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -1461,6 +1461,22 @@
 			wpa_s->wnm_dissoc_timer * beacon_int * 128 / 125, url);
 	}
 
+#ifdef CONFIG_MBO
+	vendor = get_ie(pos, end - pos, WLAN_EID_VENDOR_SPECIFIC);
+	if (vendor) {
+		wpas_mbo_ie_trans_req(wpa_s, vendor + 2, vendor[1]);
+		if (wpa_s->conf->btm_offload) {
+			wpa_msg(wpa_s, MSG_INFO,
+				"WNM: Notify BSS Transition Management Request frame status");
+			wpa_s->bss_tm_status = WNM_BSS_TM_ACCEPT;
+			wpas_notify_bss_tm_status(wpa_s);
+			/* since it could be referenced in the scan result logic, initialize it */
+			wpa_s->wnm_mbo_trans_reason_present = 0;
+			return;
+		}
+	}
+#endif /* CONFIG_MBO */
+
 	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_DISASSOC_IMMINENT) {
 		wpa_msg(wpa_s, MSG_INFO, "WNM: Disassociation Imminent - "
 			"Disassociation Timer %u", wpa_s->wnm_dissoc_timer);
@@ -1472,12 +1488,6 @@
 		}
 	}
 
-#ifdef CONFIG_MBO
-	vendor = get_ie(pos, end - pos, WLAN_EID_VENDOR_SPECIFIC);
-	if (vendor)
-		wpas_mbo_ie_trans_req(wpa_s, vendor + 2, vendor[1]);
-#endif /* CONFIG_MBO */
-
 	if (wpa_s->wnm_mode & WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED) {
 		unsigned int valid_ms;
 
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 67fb426..6ab5485 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3844,6 +3844,8 @@
 			 * succeed.
 			 */
 			wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
+			wpa_s->assoc_status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			wpas_notify_assoc_status_code(wpa_s, wpa_s->pending_bssid, 0);
 			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
 			os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
 			return;
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index c10dd73..2f1e31b 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -1646,6 +1646,12 @@
 # Set to 1 to disable BSS transition management
 #disable_btm=0
 
+# This value is used to set where to perform roaming logic
+# Set to 0 to handle roaming logic fully in supplicant
+# Set to 1 to skip roaming logic in supplicant and handle it in firmware
+# In supplicant, just parse BTM frame and notify framework
+#btm_offload=0
+
 # Enable EDMG capability in STA/AP mode, default value is false
 #enable_edmg=1