Merge "set ieee80211w to optional in hostapd config"
diff --git a/hostapd/aidl/hostapd.cpp b/hostapd/aidl/hostapd.cpp
index 9e23247..c24e4f7 100644
--- a/hostapd/aidl/hostapd.cpp
+++ b/hostapd/aidl/hostapd.cpp
@@ -298,7 +298,8 @@
 	const IfaceParams& iface_params,
 	const ChannelParams& channelParams,
 	const NetworkParams& nw_params,
-	const std::string br_name)
+	const std::string br_name,
+	const std::string owe_transition_ifname)
 {
 	if (nw_params.ssid.size() >
 		static_cast<uint32_t>(
@@ -399,6 +400,14 @@
 			is_6Ghz_band_only ? 1 : 2,
 			nw_params.passphrase.c_str());
 		break;
+	case EncryptionType::OWE_TRANSITION:
+		encryption_config_as_string = StringPrintf(
+			"wpa=2\n"
+			"rsn_pairwise=%s\n"
+			"wpa_key_mgmt=OWE\n"
+			"ieee80211w=2",
+			is_60Ghz_band_only ? "GCMP" : "CCMP");
+		break;
 	default:
 		wpa_printf(MSG_ERROR, "Unknown encryption type");
 		return "";
@@ -528,6 +537,12 @@
 		vendor_elements_as_string = StringPrintf("vendor_elements=%s", ss.str().c_str());
 	}
 
+	std::string owe_transition_ifname_as_string;
+	if (!owe_transition_ifname.empty()) {
+		owe_transition_ifname_as_string = StringPrintf(
+			"owe_transition_ifname=%s", owe_transition_ifname.c_str());
+	}
+
 	return StringPrintf(
 		"interface=%s\n"
 		"driver=nl80211\n"
@@ -551,6 +566,7 @@
 		"%s\n"
 		"%s\n"
 		"%s\n"
+		"%s\n"
 		"%s\n",
 		iface_params.name.c_str(), ssid_as_string.c_str(),
 		channel_config_as_string.c_str(),
@@ -564,6 +580,7 @@
 #endif /* CONFIG_INTERWORKING */
 		encryption_config_as_string.c_str(),
 		bridge_as_string.c_str(),
+		owe_transition_ifname_as_string.c_str(),
 		enable_edmg_as_string.c_str(),
 		edmg_channel_as_string.c_str(),
 		vendor_elements_as_string.c_str());
@@ -774,7 +791,7 @@
 		wpa_printf(MSG_INFO, "AddSingleAccessPoint, iface=%s",
 			iface_params.name.c_str());
 		return addSingleAccessPoint(iface_params, iface_params.channelParams[0],
-		    nw_params, "");
+		    nw_params, "", "");
 	} else if (channelParamsSize == 2) {
 		// Concurrent APs
 		wpa_printf(MSG_INFO, "AddDualAccessPoint, iface=%s",
@@ -784,6 +801,18 @@
 	return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
 }
 
+std::vector<uint8_t>  generateRandomOweSsid()
+{
+	u8 random[8] = {0};
+	os_get_random(random, 8);
+
+	std::string ssid = StringPrintf("Owe-%s", random);
+	wpa_printf(MSG_INFO, "Generated OWE SSID: %s", ssid.c_str());
+	std::vector<uint8_t> vssid(ssid.begin(), ssid.end());
+
+	return vssid;
+}
+
 ::ndk::ScopedAStatus Hostapd::addConcurrentAccessPoints(
 	const IfaceParams& iface_params, const NetworkParams& nw_params)
 {
@@ -803,9 +832,24 @@
 	// start BSS on specified bands
 	for (std::size_t i = 0; i < channelParamsListSize; i ++) {
 		IfaceParams iface_params_new = iface_params;
+		NetworkParams nw_params_new = nw_params;
 		iface_params_new.name = managed_interfaces[i];
+
+		std::string owe_transition_ifname = "";
+		if (nw_params.encryptionType == EncryptionType::OWE_TRANSITION) {
+			if (i == 0 && i+1 < channelParamsListSize) {
+				owe_transition_ifname = managed_interfaces[i+1];
+				nw_params_new.encryptionType = EncryptionType::NONE;
+			} else {
+				owe_transition_ifname = managed_interfaces[0];
+				nw_params_new.isHidden = true;
+				nw_params_new.ssid = generateRandomOweSsid();
+			}
+		}
+
 		ndk::ScopedAStatus status = addSingleAccessPoint(
-		    iface_params_new, iface_params.channelParams[i], nw_params, br_name);
+		    iface_params_new, iface_params.channelParams[i], nw_params_new,
+		    br_name, owe_transition_ifname);
 		if (!status.isOk()) {
 			wpa_printf(MSG_ERROR, "Failed to addAccessPoint %s",
 				   managed_interfaces[i].c_str());
@@ -821,7 +865,8 @@
 	const IfaceParams& iface_params,
 	const ChannelParams& channelParams,
 	const NetworkParams& nw_params,
-	const std::string br_name)
+	const std::string br_name,
+	const std::string owe_transition_ifname)
 {
 	if (hostapd_get_iface(interfaces_, iface_params.name.c_str())) {
 		wpa_printf(
@@ -829,7 +874,8 @@
 			iface_params.name.c_str());
 		return createStatus(HostapdStatusCode::FAILURE_IFACE_EXISTS);
 	}
-	const auto conf_params = CreateHostapdConfig(iface_params, channelParams, nw_params, br_name);
+	const auto conf_params = CreateHostapdConfig(iface_params, channelParams, nw_params,
+					br_name, owe_transition_ifname);
 	if (conf_params.empty()) {
 		wpa_printf(MSG_ERROR, "Failed to create config params");
 		return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
diff --git a/hostapd/aidl/hostapd.h b/hostapd/aidl/hostapd.h
index 18a7a23..ffdbd8e 100644
--- a/hostapd/aidl/hostapd.h
+++ b/hostapd/aidl/hostapd.h
@@ -64,7 +64,8 @@
 	    const IfaceParams& IfaceParams,
 	    const ChannelParams& channelParams,
 	    const NetworkParams& nw_params,
-	    std::string br_name);
+	    std::string br_name,
+	    std::string owe_transition_ifname);
 	::ndk::ScopedAStatus addConcurrentAccessPoints(
 	    const IfaceParams& IfaceParams,
 	    const NetworkParams& nw_params);
diff --git a/wpa_supplicant/aidl/p2p_iface.cpp b/wpa_supplicant/aidl/p2p_iface.cpp
index 8dcaad5..3dcfec8 100644
--- a/wpa_supplicant/aidl/p2p_iface.cpp
+++ b/wpa_supplicant/aidl/p2p_iface.cpp
@@ -1018,6 +1018,32 @@
 		&P2pIface::setWfdR2DeviceInfoInternal, in_info);
 }
 
+::ndk::ScopedAStatus P2pIface::removeClient(
+        const std::vector<uint8_t>& peer_address, bool isLegacyClient)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::removeClientInternal, peer_address, isLegacyClient);
+}
+
+::ndk::ScopedAStatus P2pIface::findOnSocialChannels(
+	int32_t in_timeoutInSec)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::findOnSocialChannelsInternal, in_timeoutInSec);
+}
+
+::ndk::ScopedAStatus P2pIface::findOnSpecificFrequency(
+	int32_t in_freq,
+	int32_t in_timeoutInSec)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+		&P2pIface::findOnSpecificFrequencyInternal,
+		in_freq, in_timeoutInSec);
+}
+
 std::pair<std::string, ndk::ScopedAStatus> P2pIface::getNameInternal()
 {
 	return {ifname_, ndk::ScopedAStatus::ok()};
@@ -2001,6 +2027,45 @@
 	return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus P2pIface::removeClientInternal(
+    const std::vector<uint8_t>& peer_address, bool isLegacyClient)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	wpas_p2p_remove_client(wpa_s, peer_address.data(), isLegacyClient? 1 : 0);
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::findOnSocialChannelsInternal(uint32_t timeout_in_sec)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+	}
+	uint32_t search_delay = wpas_p2p_search_delay(wpa_s);
+	if (wpas_p2p_find(
+		wpa_s, timeout_in_sec, P2P_FIND_ONLY_SOCIAL, 0, nullptr,
+		nullptr, search_delay, 0, nullptr, 0)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus P2pIface::findOnSpecificFrequencyInternal(
+	uint32_t freq, uint32_t timeout_in_sec)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
+		return createStatus(SupplicantStatusCode::FAILURE_IFACE_DISABLED);
+	}
+	uint32_t search_delay = wpas_p2p_search_delay(wpa_s);
+	if (wpas_p2p_find(
+		wpa_s, timeout_in_sec, P2P_FIND_START_WITH_FULL, 0, nullptr,
+		nullptr, search_delay, 0, nullptr, freq)) {
+		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+	}
+	return ndk::ScopedAStatus::ok();
+}
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/aidl/p2p_iface.h b/wpa_supplicant/aidl/p2p_iface.h
index d24645c..4cb86b6 100644
--- a/wpa_supplicant/aidl/p2p_iface.h
+++ b/wpa_supplicant/aidl/p2p_iface.h
@@ -164,6 +164,11 @@
 	::ndk::ScopedAStatus getEdmg(bool* _aidl_return) override;
 	::ndk::ScopedAStatus setWfdR2DeviceInfo(
 		const std::vector<uint8_t>& in_info) override;
+	::ndk::ScopedAStatus removeClient(
+		const std::vector<uint8_t>& peer_address, bool isLegacyClient) override;
+	::ndk::ScopedAStatus findOnSocialChannels(int32_t in_timeoutInSec) override;
+	::ndk::ScopedAStatus findOnSpecificFrequency(
+		int32_t in_freq, int32_t in_timeoutInSec) override;
 
 private:
 	// Corresponding worker functions for the AIDL methods.
@@ -276,6 +281,11 @@
 	std::pair<bool, ndk::ScopedAStatus> getEdmgInternal();
 	ndk::ScopedAStatus setWfdR2DeviceInfoInternal(
 		const std::vector<uint8_t>& info);
+	ndk::ScopedAStatus removeClientInternal(
+		const std::vector<uint8_t>& peer_address, bool isLegacyClient);
+	ndk::ScopedAStatus findOnSocialChannelsInternal(uint32_t timeout_in_sec);
+	ndk::ScopedAStatus findOnSpecificFrequencyInternal(
+		uint32_t freq, uint32_t timeout_in_sec);
 
 	struct wpa_supplicant* retrieveIfacePtr();
 	struct wpa_supplicant* retrieveGroupIfacePtr(
diff --git a/wpa_supplicant/aidl/sta_iface.cpp b/wpa_supplicant/aidl/sta_iface.cpp
index abde780..9b967e4 100644
--- a/wpa_supplicant/aidl/sta_iface.cpp
+++ b/wpa_supplicant/aidl/sta_iface.cpp
@@ -770,6 +770,31 @@
 		&StaIface::setMboCellularDataStatusInternal, in_available);
 }
 
+::ndk::ScopedAStatus StaIface::setQosPolicyFeatureEnabled(
+	bool in_enable)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_UNKNOWN,
+		&StaIface::setQosPolicyFeatureEnabledInternal, in_enable);
+}
+
+::ndk::ScopedAStatus StaIface::sendQosPolicyResponse(
+	bool in_morePolicies,
+	const std::vector<QosPolicyStatus>& in_qosPolicyStatusList)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_UNKNOWN,
+		&StaIface::sendQosPolicyResponseInternal, in_morePolicies,
+		in_qosPolicyStatusList);
+}
+
+::ndk::ScopedAStatus StaIface::removeAllQosPolicies()
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_UNKNOWN,
+		&StaIface::removeAllQosPoliciesInternal);
+}
+
 std::pair<std::string, ndk::ScopedAStatus> StaIface::getNameInternal()
 {
 	return {ifname_, ndk::ScopedAStatus::ok()};
@@ -1742,6 +1767,22 @@
 		ndk::ScopedAStatus::ok()};
 }
 
+ndk::ScopedAStatus StaIface::setQosPolicyFeatureEnabledInternal(bool enable)
+{
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::sendQosPolicyResponseInternal(
+	bool more_policies, const std::vector<QosPolicyStatus>& qos_policy_status_list)
+{
+	return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StaIface::removeAllQosPoliciesInternal()
+{
+	return ndk::ScopedAStatus::ok();
+}
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/aidl/sta_iface.h b/wpa_supplicant/aidl/sta_iface.h
index 98c3187..0853b7e 100644
--- a/wpa_supplicant/aidl/sta_iface.h
+++ b/wpa_supplicant/aidl/sta_iface.h
@@ -20,6 +20,7 @@
 #include <aidl/android/hardware/wifi/supplicant/Hs20AnqpSubtypes.h>
 #include <aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.h>
 #include <aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.h>
+#include <aidl/android/hardware/wifi/supplicant/QosPolicyStatus.h>
 #include <aidl/android/hardware/wifi/supplicant/RxFilterType.h>
 
 extern "C"
@@ -145,6 +146,10 @@
 		DppResponderBootstrapInfo* _aidl_return) override;
 	::ndk::ScopedAStatus startDppEnrolleeResponder(int32_t in_listenChannel) override;
 	::ndk::ScopedAStatus stopDppResponder(int32_t in_ownBootstrapId) override;
+	::ndk::ScopedAStatus setQosPolicyFeatureEnabled(bool in_enable) override;
+	::ndk::ScopedAStatus sendQosPolicyResponse(
+		bool in_morePolicies, const std::vector<QosPolicyStatus>& in_qosPolicyStatusList) override;
+	::ndk::ScopedAStatus removeAllQosPolicies() override;
 
 private:
 	// Corresponding worker functions for the AIDL methods.
@@ -241,6 +246,10 @@
 			DppCurve curve);
 	ndk::ScopedAStatus startDppEnrolleeResponderInternal(uint32_t listen_channel);
 	ndk::ScopedAStatus stopDppResponderInternal(uint32_t own_bootstrap_id);
+	ndk::ScopedAStatus setQosPolicyFeatureEnabledInternal(bool enable);
+	ndk::ScopedAStatus sendQosPolicyResponseInternal(
+		bool more_policies, const std::vector<QosPolicyStatus>& qos_policy_status_list);
+	ndk::ScopedAStatus removeAllQosPoliciesInternal();
 
 	struct wpa_supplicant* retrieveIfacePtr();
 
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 36f4d3c..5a771e8 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -663,7 +663,11 @@
 	}
 
 #ifdef CONFIG_HS20
-	if (is_hs20_config(wpa_s) && is_hs20_network(wpa_s, ssid, bss)) {
+	if (is_hs20_network(wpa_s, ssid, bss)
+#ifndef ANDROID /* Android does not use the native HS 2.0 config */
+			&& is_hs20_config(wpa_s)
+#endif /* ANDROID */
+	) {
 		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 5cc6952..df3bb35 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3046,7 +3046,11 @@
 	}
 
 #ifdef CONFIG_HS20
-	if (is_hs20_config(wpa_s) && is_hs20_network(wpa_s, ssid, bss)) {
+	if (is_hs20_network(wpa_s, ssid, bss)
+#ifndef ANDROID /* Android does not use the native HS 2.0 config */
+			&& is_hs20_config(wpa_s)
+#endif /* ANDROID */
+	) {
 		struct wpabuf *hs20;
 
 		hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);