Merge "Revert "Wifi: Support NVT-ASCII in passphrase"" into sc-dev
diff --git a/hostapd/hidl/1.3/hostapd.cpp b/hostapd/hidl/1.3/hostapd.cpp
index 1a342e5..3b2e4c9 100644
--- a/hostapd/hidl/1.3/hostapd.cpp
+++ b/hostapd/hidl/1.3/hostapd.cpp
@@ -535,9 +535,10 @@
 
 Generation getGeneration(hostapd_hw_modes *current_mode)
 {
-	wpa_printf(MSG_DEBUG, "getGeneration hwmode=%d, ht_enabled=%d, vht_enabled=%d",
+	wpa_printf(MSG_DEBUG, "getGeneration hwmode=%d, ht_enabled=%d,"
+		   " vht_enabled=%d, he_supported=%d",
 		   current_mode->mode, current_mode->ht_capab != 0,
-		   current_mode->vht_capab != 0);
+		   current_mode->vht_capab != 0, current_mode->he_capab->he_supported);
 	switch (current_mode->mode) {
 	case HOSTAPD_MODE_IEEE80211B:
 		return Generation::WIFI_STANDARD_LEGACY;
@@ -545,11 +546,13 @@
 		return current_mode->ht_capab == 0 ?
 		       Generation::WIFI_STANDARD_LEGACY : Generation::WIFI_STANDARD_11N;
 	case HOSTAPD_MODE_IEEE80211A:
+		if (current_mode->he_capab->he_supported) {
+			return Generation::WIFI_STANDARD_11AX;
+		}
 		return current_mode->vht_capab == 0 ?
 		       Generation::WIFI_STANDARD_11N : Generation::WIFI_STANDARD_11AC;
 	case HOSTAPD_MODE_IEEE80211AD:
 		return Generation::WIFI_STANDARD_11AD;
-        // TODO: b/162484222 miss HOSTAPD_MODE_IEEE80211AX definition.
 	default:
 		return Generation::WIFI_STANDARD_UNKNOWN;
 	}
@@ -935,13 +938,31 @@
 
 V1_0::HostapdStatus Hostapd::removeAccessPointInternal(const std::string& iface_name)
 {
-	std::vector<char> remove_iface_param_vec(
-	    iface_name.begin(), iface_name.end() + 1);
-	if (hostapd_remove_iface(interfaces_, remove_iface_param_vec.data()) <
-	    0) {
-		wpa_printf(
-		    MSG_ERROR, "Removing interface %s failed",
-		    iface_name.c_str());
+	// interfaces to be removed
+	std::vector<std::string> interfaces;
+	bool is_error = false;
+
+	const auto it = br_interfaces_.find(iface_name);
+	if (it != br_interfaces_.end()) {
+		// In case bridge, remove managed interfaces
+		interfaces = it->second;
+		br_interfaces_.erase(iface_name);
+	} else {
+		// else remove current interface
+		interfaces.push_back(iface_name);
+	}
+
+	for (auto& iface : interfaces) {
+		std::vector<char> remove_iface_param_vec(
+		    iface.begin(), iface.end() + 1);
+		if (hostapd_remove_iface(interfaces_, remove_iface_param_vec.data()) <
+		    0) {
+			wpa_printf(MSG_INFO, "Remove interface %s failed",
+			    iface.c_str());
+			is_error = true;
+		}
+	}
+	if (is_error) {
 		return {V1_0::HostapdStatusCode::FAILURE_UNKNOWN, ""};
 	}
 	return {V1_0::HostapdStatusCode::SUCCESS, ""};
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index ba2599e..5d4f71e 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -6809,6 +6809,7 @@
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 	int was_ap = is_ap_interface(drv->nlmode);
+	int br_ifindex;
 
 	wpa_driver_nl80211_set_mode(bss, drv->ap_scan_as_station);
 	if (!was_ap && is_ap_interface(drv->ap_scan_as_station) &&
@@ -6823,6 +6824,8 @@
 				   "nl80211: Failed to add interface %s into bridge %s: %s",
 				   bss->ifname, bss->brname, strerror(errno));
 		}
+		br_ifindex = if_nametoindex(bss->brname);
+		add_ifidx(drv, br_ifindex, drv->ifindex);
 	}
 	drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED;
 }
diff --git a/src/eap_common/eap_sim_common.c b/src/eap_common/eap_sim_common.c
index 4a93244..ea38e6a 100644
--- a/src/eap_common/eap_sim_common.c
+++ b/src/eap_common/eap_sim_common.c
@@ -1209,10 +1209,23 @@
 	}
 }
 
+static const u8 * get_last_char(const u8 *val, size_t len, char c)
+{
+	while (len > 0) {
+		const u8 *pos = &val[len - 1];
+
+		if (*pos == (u8) c)
+			return pos;
+		len--;
+	}
+
+	return NULL;
+}
 
 int eap_sim_anonymous_username(const u8 *id, size_t id_len)
 {
 	static const char *anonymous_id_prefix = "anonymous@";
+	const u8 *decorated;
 	size_t anonymous_id_len = os_strlen(anonymous_id_prefix);
 
 	if (id_len > anonymous_id_len &&
@@ -1226,5 +1239,14 @@
 	if (id_len > 1 && id[0] == '@')
 		return 1; /* '@realm' */
 
+	/* RFC 7542 decorated username, for example:
+	 * homerealm.example.org!anonymous@otherrealm.example.net */
+	decorated = get_last_char(id, id_len, '!');
+	if (decorated) {
+		decorated++;
+		return eap_sim_anonymous_username(decorated,
+						  id + id_len - decorated);
+	}
 	return 0;
 }
+
diff --git a/wpa_supplicant/hidl/1.4/hidl.cpp b/wpa_supplicant/hidl/1.4/hidl.cpp
index 1e55305..649772a 100644
--- a/wpa_supplicant/hidl/1.4/hidl.cpp
+++ b/wpa_supplicant/hidl/1.4/hidl.cpp
@@ -397,7 +397,8 @@
 void wpas_hidl_notify_p2p_device_found(
     struct wpa_supplicant *wpa_s, const u8 *addr,
     const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-    u8 peer_wfd_device_info_len)
+    u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+    u8 peer_wfd_r2_device_info_len)
 {
 	if (!wpa_s || !addr || !info)
 		return;
@@ -411,7 +412,9 @@
 		return;
 
 	hidl_manager->notifyP2pDeviceFound(
-	    wpa_s, addr, info, peer_wfd_device_info, peer_wfd_device_info_len);
+	    wpa_s, addr, info, peer_wfd_device_info,
+	    peer_wfd_device_info_len, peer_wfd_r2_device_info,
+	    peer_wfd_r2_device_info_len);
 }
 
 void wpas_hidl_notify_p2p_device_lost(
diff --git a/wpa_supplicant/hidl/1.4/hidl.h b/wpa_supplicant/hidl/1.4/hidl.h
index 1d67d82..0974048 100644
--- a/wpa_supplicant/hidl/1.4/hidl.h
+++ b/wpa_supplicant/hidl/1.4/hidl.h
@@ -65,7 +65,8 @@
 	void wpas_hidl_notify_p2p_device_found(
 	    struct wpa_supplicant *wpa_s, const u8 *addr,
 	    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-	    u8 peer_wfd_device_info_len);
+	    u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+	    u8 peer_wfd_r2_device_info_len);
 	void wpas_hidl_notify_p2p_device_lost(
 	    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr);
 	void wpas_hidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s);
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.cpp b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
index b7a7cf7..4a09da1 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
@@ -24,6 +24,7 @@
 using android::hardware::hidl_array;
 
 constexpr uint8_t kWfdDeviceInfoLen = 6;
+constexpr uint8_t kWfdR2DeviceInfoLen = 2;
 // GSM-AUTH:<RAND1>:<RAND2>[:<RAND3>]
 constexpr char kGsmAuthRegex2[] = "GSM-AUTH:([0-9a-f]+):([0-9a-f]+)";
 constexpr char kGsmAuthRegex3[] =
@@ -414,6 +415,8 @@
 namespace V1_4 {
 namespace implementation {
 using V1_0::ISupplicantStaIfaceCallback;
+using V1_0::ISupplicantP2pIfaceCallback;
+using ISupplicantP2pIfaceCallbackV1_4 = V1_4::ISupplicantP2pIfaceCallback;
 
 HidlManager *HidlManager::instance_ = NULL;
 
@@ -1224,7 +1227,8 @@
 void HidlManager::notifyP2pDeviceFound(
     struct wpa_supplicant *wpa_s, const u8 *addr,
     const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-    u8 peer_wfd_device_info_len)
+    u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+    u8 peer_wfd_r2_device_info_len)
 {
 	if (!wpa_s || !addr || !info)
 		return;
@@ -1246,13 +1250,39 @@
 		}
 	}
 
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onDeviceFound,
-		std::placeholders::_1, addr, info->p2p_device_addr,
-		info->pri_dev_type, info->device_name, info->config_methods,
-		info->dev_capab, info->group_capab, hidl_peer_wfd_device_info));
+	std::array<uint8_t, kWfdR2DeviceInfoLen> hidl_peer_wfd_r2_device_info{};
+	if (peer_wfd_r2_device_info) {
+		if (peer_wfd_r2_device_info_len != kWfdR2DeviceInfoLen) {
+			wpa_printf(
+			    MSG_ERROR, "Unexpected WFD R2 device info len: %d",
+			    peer_wfd_r2_device_info_len);
+			return;
+		} else {
+			os_memcpy(
+			    hidl_peer_wfd_r2_device_info.data(),
+			    peer_wfd_r2_device_info, kWfdR2DeviceInfoLen);
+		}
+	}
+
+	if (peer_wfd_r2_device_info_len == kWfdR2DeviceInfoLen) {
+		const std::function<
+		    Return<void>(android::sp<V1_4::ISupplicantP2pIfaceCallback>)>
+		    func = std::bind(
+			&ISupplicantP2pIfaceCallbackV1_4::onR2DeviceFound,
+			std::placeholders::_1, addr, info->p2p_device_addr,
+			info->pri_dev_type, info->device_name, info->config_methods,
+			info->dev_capab, info->group_capab, hidl_peer_wfd_device_info,
+			hidl_peer_wfd_r2_device_info);
+		callWithEachP2pIfaceCallbackDerived(wpa_s->ifname, func);
+	} else {
+		callWithEachP2pIfaceCallback(
+		    wpa_s->ifname,
+		    std::bind(
+			&ISupplicantP2pIfaceCallback::onDeviceFound,
+			std::placeholders::_1, addr, info->p2p_device_addr,
+			info->pri_dev_type, info->device_name, info->config_methods,
+			info->dev_capab, info->group_capab, hidl_peer_wfd_device_info));
+	}
 }
 
 void HidlManager::notifyP2pDeviceLost(
@@ -1815,7 +1845,7 @@
 		//wnm_bss_termination_duration contains 12 bytes of BSS
 		//termination duration subelement. Format of IE is
 		// Sub eid | Length | BSS termination TSF | Duration
-		//    1         1             8                2
+		//    1	 1	     8		2
 		// Duration indicates number of minutes for which BSS is not
 		// present.
 		duration_ms = WPA_GET_LE16(wpa_s->wnm_bss_termination_duration + 10);
@@ -2276,6 +2306,24 @@
 
 /**
  * Helper function to invoke the provided callback method on all the
+ * registered derived interface callback hidl objects for the specified
+ * |ifname|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param method Pointer to the required hidl method from
+ * derived |V1_x::ISupplicantIfaceCallback|.
+ */
+template <class CallbackTypeDerived>
+void HidlManager::callWithEachP2pIfaceCallbackDerived(
+    const std::string &ifname,
+    const std::function<
+	Return<void>(android::sp<CallbackTypeDerived>)> &method)
+{
+	callWithEachIfaceCallbackDerived(ifname, method, p2p_iface_callbacks_map_);
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
  * registered V1.1 interface callback hidl objects for the specified
  * |ifname|.
  *
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.h b/wpa_supplicant/hidl/1.4/hidl_manager.h
index 21b2ed4..ccde11c 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.h
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.h
@@ -118,7 +118,8 @@
 	void notifyP2pDeviceFound(
 	    struct wpa_supplicant *wpa_s, const u8 *addr,
 	    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-	    u8 peer_wfd_device_info_len);
+	    u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+	    u8 peer_wfd_r2_device_info_len);
 	void notifyP2pDeviceLost(
 	    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr);
 	void notifyP2pFindStopped(struct wpa_supplicant *wpa_s);
@@ -236,6 +237,11 @@
 	    const std::string &ifname,
 	    const std::function<android::hardware::Return<void>(
 		android::sp<ISupplicantP2pIfaceCallback>)> &method);
+	template <class CallbackTypeDerived>
+	void callWithEachP2pIfaceCallbackDerived(
+	    const std::string &ifname,
+	    const std::function<
+		Return<void>(android::sp<CallbackTypeDerived>)> &method);
 	void callWithEachStaIfaceCallback(
 	    const std::string &ifname,
 	    const std::function<android::hardware::Return<void>(
diff --git a/wpa_supplicant/hidl/1.4/p2p_iface.cpp b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
index 7baffa2..16fd11a 100644
--- a/wpa_supplicant/hidl/1.4/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
@@ -33,6 +33,7 @@
 const char kConfigMethodStrKeypad[] = "keypad";
 constexpr char kSetMiracastMode[] = "MIRACAST ";
 constexpr uint8_t kWfdDeviceInfoSubelemId = 0;
+constexpr uint8_t kWfdR2DeviceInfoSubelemId = 11;
 constexpr char kWfdDeviceInfoSubelemLenHexStr[] = "0006";
 
 std::function<void()> pending_join_scan_callback = NULL;
@@ -895,6 +896,23 @@
 	    &P2pIface::getEdmgInternal, _hidl_cb);
 }
 
+Return<void> P2pIface::registerCallback_1_4(
+    const sp<V1_4::ISupplicantP2pIfaceCallback>& callback,
+    registerCallback_1_4_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::registerCallback_1_4Internal, _hidl_cb, callback);
+}
+
+Return<void> P2pIface::setWfdR2DeviceInfo(
+    const hidl_array<uint8_t, 4>& info, setWfdR2DeviceInfo_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setWfdR2DeviceInfoInternal, _hidl_cb, info);
+}
+
 std::pair<SupplicantStatus, std::string> P2pIface::getNameInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
@@ -1855,6 +1873,40 @@
 		(wpa_s->p2p_go_edmg == 1)};
 }
 
+V1_4::SupplicantStatus P2pIface::registerCallback_1_4Internal(
+    const sp<V1_4::ISupplicantP2pIfaceCallback>& callback)
+{
+	HidlManager* hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->addP2pIfaceCallbackHidlObject(ifname_, callback)) {
+		return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+}
+
+V1_4::SupplicantStatus P2pIface::setWfdR2DeviceInfoInternal(
+    const std::array<uint8_t, 4>& info)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	uint32_t wfd_r2_device_info_hex_len = info.size() * 2 + 1;
+	std::vector<char> wfd_r2_device_info_hex(wfd_r2_device_info_hex_len);
+	wpa_snprintf_hex(
+	    wfd_r2_device_info_hex.data(), wfd_r2_device_info_hex.size(),
+	    info.data(),info.size());
+	std::string wfd_r2_device_info_set_cmd_str =
+	     std::to_string(kWfdR2DeviceInfoSubelemId) + " " +
+	     wfd_r2_device_info_hex.data();
+	std::vector<char> wfd_r2_device_info_set_cmd(
+	     wfd_r2_device_info_set_cmd_str.c_str(),
+	     wfd_r2_device_info_set_cmd_str.c_str() +
+	     wfd_r2_device_info_set_cmd_str.size() + 1);
+	if (wifi_display_subelem_set(
+		wpa_s->global, wfd_r2_device_info_set_cmd.data())) {
+		return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+}
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/hidl/1.4/p2p_iface.h b/wpa_supplicant/hidl/1.4/p2p_iface.h
index 1694efe..c8ddc01 100644
--- a/wpa_supplicant/hidl/1.4/p2p_iface.h
+++ b/wpa_supplicant/hidl/1.4/p2p_iface.h
@@ -200,6 +200,12 @@
 	    bool enable, setMacRandomization_cb _hidl_cb) override;
 	Return<void> setEdmg(bool enable, setEdmg_cb _hidl_cb) override;
 	Return<void> getEdmg(getEdmg_cb _hidl_cb) override;
+	Return<void> registerCallback_1_4(
+	    const sp<V1_4::ISupplicantP2pIfaceCallback>& callback,
+	    registerCallback_1_4_cb _hidl_cb) override;
+	Return<void> setWfdR2DeviceInfo(
+	    const hidl_array<uint8_t, 4>& info,
+	    setWfdR2DeviceInfo_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -311,6 +317,10 @@
 	SupplicantStatus setMacRandomizationInternal(bool enable);
 	V1_4::SupplicantStatus setEdmgInternal(bool enable);
 	std::pair<V1_4::SupplicantStatus, bool> getEdmgInternal();
+	V1_4::SupplicantStatus registerCallback_1_4Internal(
+	    const sp<V1_4::ISupplicantP2pIfaceCallback>& callback);
+	V1_4::SupplicantStatus setWfdR2DeviceInfoInternal(
+	    const std::array<uint8_t, 4>& info);
 
 	struct wpa_supplicant* retrieveIfacePtr();
 	struct wpa_supplicant* retrieveGroupIfacePtr(
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.cpp b/wpa_supplicant/hidl/1.4/sta_iface.cpp
index 731808d..1bf279e 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_iface.cpp
@@ -1756,6 +1756,7 @@
 #ifdef CONFIG_SAE_PK
 	mask |= V1_4::WpaDriverCapabilitiesMask::SAE_PK;
 #endif
+	mask |= V1_4::WpaDriverCapabilitiesMask::WFD_R2;
 
 	wpa_printf(MSG_DEBUG, "Driver capability mask: 0x%x", mask);
 
diff --git a/wpa_supplicant/hidl/1.4/sta_network.cpp b/wpa_supplicant/hidl/1.4/sta_network.cpp
index 3e773de..ee132ac 100644
--- a/wpa_supplicant/hidl/1.4/sta_network.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_network.cpp
@@ -96,9 +96,6 @@
 constexpr char kNetworkEapSimUmtsAutsResponse[] = "UMTS-AUTS";
 constexpr char kNetworkEapSimGsmAuthFailure[] = "GSM-FAIL";
 constexpr char kNetworkEapSimUmtsAuthFailure[] = "UMTS-FAIL";
-/* These constants refer definitions in wpa_supplicant/config.h */
-constexpr int SAE_PWE_H2E_ONLY_MODE = 1;
-constexpr int SAE_PWE_HP_H2E_BOTH = 2;
 
 #ifdef CONFIG_WAPI_INTERFACE
 std::string dummyWapiCertSuite;
@@ -990,11 +987,12 @@
 	    &StaNetwork::getPairwiseCipher_1_4Internal, _hidl_cb);
 }
 
-Return<void> StaNetwork::enableSaeH2eOnlyMode(bool enable, enableSaeH2eOnlyMode_cb _hidl_cb)
+Return<void> StaNetwork::setSaeH2eMode(
+    ISupplicantStaNetworkV1_4::SaeH2eMode mode, setSaeH2eMode_cb _hidl_cb)
 {
 	return validateAndCall(
 	    this, V1_4::SupplicantStatusCode::FAILURE_NETWORK_INVALID,
-	    &StaNetwork::enableSaeH2eOnlyModeInternal, _hidl_cb, enable);
+	    &StaNetwork::setSaeH2eModeInternal, _hidl_cb, mode);
 }
 
 Return<void> StaNetwork::enableSaePkOnlyMode(bool enable, enableSaePkOnlyMode_cb _hidl_cb)
@@ -2620,10 +2618,21 @@
 #endif /* CONFIG_FILS */
 }
 
-V1_4::SupplicantStatus StaNetwork::enableSaeH2eOnlyModeInternal(bool enable)
+V1_4::SupplicantStatus StaNetwork::setSaeH2eModeInternal(
+    ISupplicantStaNetworkV1_4::SaeH2eMode mode)
 {
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
-	wpa_s->conf->sae_pwe = enable ? SAE_PWE_H2E_ONLY_MODE : SAE_PWE_HP_H2E_BOTH;
+	switch (mode) {
+	case ISupplicantStaNetworkV1_4::SaeH2eMode::DISABLED:
+		wpa_s->conf->sae_pwe = 0;
+		break;
+	case ISupplicantStaNetworkV1_4::SaeH2eMode::H2E_MANDATORY:
+		wpa_s->conf->sae_pwe = 1;
+		break;
+	case ISupplicantStaNetworkV1_4::SaeH2eMode::H2E_OPTIONAL:
+		wpa_s->conf->sae_pwe = 2;
+		break;
+	}
 	resetInternalStateAfterParamsUpdate();
 	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
 }
diff --git a/wpa_supplicant/hidl/1.4/sta_network.h b/wpa_supplicant/hidl/1.4/sta_network.h
index 48bf77b..152f00f 100644
--- a/wpa_supplicant/hidl/1.4/sta_network.h
+++ b/wpa_supplicant/hidl/1.4/sta_network.h
@@ -271,7 +271,8 @@
 	    setGroupCipher_1_4_cb _hidl_cb) override;
 	Return<void> getGroupCipher_1_4(
 	    getGroupCipher_1_4_cb _hidl_cb) override;
-	Return<void> enableSaeH2eOnlyMode(bool enable, enableSaeH2eOnlyMode_cb _hidl_cb) override;
+	Return<void> setSaeH2eMode(V1_4::ISupplicantStaNetwork::SaeH2eMode mode,
+	    setSaeH2eMode_cb _hidl_cb) override;
 	Return<void> enableSaePkOnlyMode(bool enable, enableSaePkOnlyMode_cb _hidl_cb) override;
 
 private:
@@ -414,7 +415,7 @@
 	std::pair<V1_4::SupplicantStatus, uint32_t> getPairwiseCipher_1_4Internal();
 	V1_4::SupplicantStatus setPairwiseCipher_1_4Internal(
 	    uint32_t pairwise_cipher_mask);
-	V1_4::SupplicantStatus enableSaeH2eOnlyModeInternal(bool enable);
+	V1_4::SupplicantStatus setSaeH2eModeInternal(V1_4::ISupplicantStaNetwork::SaeH2eMode mode);
 	V1_4::SupplicantStatus enableSaePkOnlyModeInternal(bool enable);
 
 	struct wpa_ssid* retrieveNetworkPtr();
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index 8aeb3b0..eaf0803 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -73,7 +73,12 @@
 	const u8 *ext_capa;
 	u32 filter = 0;
 
-	if (!bss || !is_hs20_network(wpa_s, wpa_s->current_ssid, bss)) {
+	if (!bss || !is_hs20_network(wpa_s, wpa_s->current_ssid, bss)
+#ifndef ANDROID
+			// HS 2.0 Configuration is not used in AOSP
+			|| !is_hs20_config(wpa_s)
+#endif
+			) {
 		wpa_printf(MSG_DEBUG,
 			   "Not configuring frame filtering - BSS " MACSTR
 			   " is not a Hotspot 2.0 network", MAC2STR(bssid));
@@ -158,11 +163,15 @@
 	return ((ie[6] >> 4) & 0x0f) + 1;
 }
 
+int is_hs20_config(struct wpa_supplicant *wpa_s)
+{
+	return wpa_s->conf->hs20;
+}
 
 int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
 		    struct wpa_bss *bss)
 {
-	if (!wpa_s->conf->hs20 || !ssid)
+	if (!ssid)
 		return 0;
 
 	if (ssid->parent_cred)
diff --git a/wpa_supplicant/hs20_supplicant.h b/wpa_supplicant/hs20_supplicant.h
index e43414b..2d478f4 100644
--- a/wpa_supplicant/hs20_supplicant.h
+++ b/wpa_supplicant/hs20_supplicant.h
@@ -22,6 +22,7 @@
 				  struct wpa_bss *bss, const u8 *sa,
 				  const u8 *data, size_t slen, u8 dialog_token);
 int get_hs20_version(struct wpa_bss *bss);
+int is_hs20_config(struct wpa_supplicant *wpa_s);
 int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
 		    struct wpa_bss *bss);
 int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index d62c96d..5508f16 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -647,6 +647,7 @@
 void wpas_notify_p2p_device_found(struct wpa_supplicant *wpa_s,
 				  const u8 *addr, const struct p2p_peer_info *info,
 				  const u8* peer_wfd_device_info, u8 peer_wfd_device_info_len,
+				  const u8* peer_wfd_r2_device_info, u8 peer_wfd_r2_device_info_len,
 				  int new_device)
 {
 	if (new_device) {
@@ -659,7 +660,9 @@
 
 	wpas_hidl_notify_p2p_device_found(wpa_s, addr, info,
 					  peer_wfd_device_info,
-					  peer_wfd_device_info_len);
+					  peer_wfd_device_info_len,
+					  peer_wfd_r2_device_info,
+					  peer_wfd_r2_device_info_len);
 }
 
 
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index a2b3183..706573c 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -101,6 +101,7 @@
 void wpas_notify_p2p_device_found(struct wpa_supplicant *wpa_s,
 				 const u8 *addr, const struct p2p_peer_info *info,
 				 const u8* peer_wfd_device_info, u8 peer_wfd_device_info_len,
+				 const u8* peer_wfd_r2_device_info, u8 peer_wfd_r2_device_info_len,
 				 int new_device);
 void wpas_notify_p2p_device_lost(struct wpa_supplicant *wpa_s,
 				 const u8 *dev_addr);
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 45c8744..a7e7587 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -2495,10 +2495,13 @@
 {
 	u8 *wfd_dev_info = NULL;
 	u8 wfd_dev_info_len = 0;
+	u8 *wfd_r2_dev_info = NULL;
+	u8 wfd_r2_dev_info_len = 0;
 #ifndef CONFIG_NO_STDOUT_DEBUG
 	struct wpa_supplicant *wpa_s = ctx;
 	char devtype[WPS_DEV_TYPE_BUFSIZE];
 	char *wfd_dev_info_hex = NULL;
+	char *wfd_r2_dev_info_hex = NULL;
 
 #ifdef CONFIG_WIFI_DISPLAY
 	wfd_dev_info_hex = wifi_display_subelem_hex(info->wfd_subelems,
@@ -2509,6 +2512,15 @@
 		// Only used for notification, so not handling error.
 		hexstr2bin(wfd_dev_info_hex, wfd_dev_info, wfd_dev_info_len);
 	}
+
+	wfd_r2_dev_info_hex = wifi_display_subelem_hex(info->wfd_subelems,
+						    WFD_SUBELEM_R2_DEVICE_INFO);
+	if (wfd_r2_dev_info_hex) {
+		wfd_r2_dev_info_len = strlen(wfd_r2_dev_info_hex) / 2;
+		wfd_r2_dev_info = os_zalloc(wfd_r2_dev_info_len);
+		// Only used for notification, so not handling error.
+		hexstr2bin(wfd_r2_dev_info_hex, wfd_r2_dev_info, wfd_r2_dev_info_len);
+	}
 #endif /* CONFIG_WIFI_DISPLAY */
 
 	if (info->p2ps_instance) {
@@ -2560,7 +2572,7 @@
 	wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_DEVICE_FOUND MACSTR
 		       " p2p_dev_addr=" MACSTR
 		       " pri_dev_type=%s name='%s' config_methods=0x%x "
-		       "dev_capab=0x%x group_capab=0x%x%s%s%s new=%d",
+		       "dev_capab=0x%x group_capab=0x%x%s%s%s%s%s new=%d",
 		       MAC2STR(addr), MAC2STR(info->p2p_device_addr),
 		       wps_dev_type_bin2str(info->pri_dev_type, devtype,
 					    sizeof(devtype)),
@@ -2568,15 +2580,19 @@
 		       info->dev_capab, info->group_capab,
 		       wfd_dev_info_hex ? " wfd_dev_info=0x" : "",
 		       wfd_dev_info_hex ? wfd_dev_info_hex : "",
+		       wfd_r2_dev_info_hex ? " wfd_r2_dev_info=0x" : "",
+		       wfd_r2_dev_info_hex ? wfd_r2_dev_info_hex : "",
 		       info->vendor_elems ? " vendor_elems=1" : "",
 		       new_device);
 
 done:
 	os_free(wfd_dev_info_hex);
+	os_free(wfd_r2_dev_info_hex);
 #endif /* CONFIG_NO_STDOUT_DEBUG */
 
 	wpas_notify_p2p_device_found(ctx, addr, info, wfd_dev_info,
-				     wfd_dev_info_len, new_device);
+				     wfd_dev_info_len, wfd_r2_dev_info,
+				     wfd_r2_dev_info_len, new_device);
 	os_free(wfd_dev_info);
 }
 
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index c6cef5b..36f4d3c 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -663,7 +663,7 @@
 	}
 
 #ifdef CONFIG_HS20
-	if (is_hs20_network(wpa_s, ssid, bss)) {
+	if (is_hs20_config(wpa_s) && is_hs20_network(wpa_s, ssid, bss)) {
 		struct wpabuf *hs20;
 
 		hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 1fd6506..224fb10 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1016,6 +1016,9 @@
 		if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE))
 			wpas_update_owe_connect_params(wpa_s);
 #endif /* CONFIG_OWE */
+#ifdef CONFIG_HS20
+		hs20_configure_frame_filters(wpa_s);
+#endif
 	} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
 		   state == WPA_ASSOCIATED) {
 		wpa_s->new_connection = 1;
@@ -3033,7 +3036,7 @@
 	}
 
 #ifdef CONFIG_HS20
-	if (is_hs20_network(wpa_s, ssid, bss)) {
+	if (is_hs20_config(wpa_s) && is_hs20_network(wpa_s, ssid, bss)) {
 		struct wpabuf *hs20;
 
 		hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
@@ -3051,10 +3054,9 @@
 				wpa_ie_len += wpabuf_len(hs20);
 			}
 			wpabuf_free(hs20);
-
-			hs20_configure_frame_filters(wpa_s);
 		}
 	}
+	hs20_configure_frame_filters(wpa_s);
 #endif /* CONFIG_HS20 */
 
 	if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {