Merge "[wpa_supplicant] cumilative patch from commit a8655be0b" into main
diff --git a/hostapd/Android.bp b/hostapd/Android.bp
index 8b79dd5..fb414d0 100644
--- a/hostapd/Android.bp
+++ b/hostapd/Android.bp
@@ -355,3 +355,10 @@
         "src/utils/wpa_debug.c",
     ],
 }
+
+prebuilt_etc {
+    name: "android.hardware.wifi.hostapd.xml.prebuilt",
+    src: "android.hardware.wifi.hostapd.xml",
+    relative_install_path: "vintf",
+    installable: false,
+}
diff --git a/hostapd/aidl/hostapd.cpp b/hostapd/aidl/hostapd.cpp
index afb4147..9c485e7 100644
--- a/hostapd/aidl/hostapd.cpp
+++ b/hostapd/aidl/hostapd.cpp
@@ -120,10 +120,16 @@
 }
 
 std::string WriteHostapdConfig(
-    const std::string& interface_name, const std::string& config)
+    const std::string& instance_name, const std::string& config,
+    const std::string br_name, const bool usesMlo)
 {
+	std::string conf_name_as_string = instance_name;
+	if (usesMlo) {
+		conf_name_as_string = StringPrintf(
+				"%s-%s", br_name.c_str(), instance_name.c_str());
+	}
 	const std::string file_path =
-	    StringPrintf(kConfFileNameFmt, interface_name.c_str());
+		StringPrintf(kConfFileNameFmt, conf_name_as_string.c_str());
 	if (WriteStringToFile(
 		config, file_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
 		getuid(), getgid())) {
@@ -588,16 +594,24 @@
 	if (iface_params.hwModeParams.enable80211BE && !is_60Ghz_used) {
 		eht_params_as_string = "ieee80211be=1\n";
 		if (isAidlServiceVersionAtLeast(2) && isAidlClientVersionAtLeast(2)) {
-			std::string interface_mac_addr = getInterfaceMacAddress(iface_params.name);
+			std::string interface_mac_addr = getInterfaceMacAddress(
+					iface_params.usesMlo ? br_name : iface_params.name);
 			if (interface_mac_addr.empty()) {
 				wpa_printf(MSG_ERROR,
 				    "Unable to set interface mac address as bssid for 11BE SAP");
 				return "";
 			}
-			eht_params_as_string += StringPrintf(
-				"bssid=%s\n"
-				"mld_ap=1",
-				interface_mac_addr.c_str());
+            if (iface_params.usesMlo) {
+                eht_params_as_string += StringPrintf(
+                    "mld_addr=%s\n"
+                    "mld_ap=1",
+                    interface_mac_addr.c_str());
+            } else {
+                eht_params_as_string += StringPrintf(
+                    "bssid=%s\n"
+                    "mld_ap=1",
+                    interface_mac_addr.c_str());
+            }
 		}
 		/* TODO set eht_su_beamformer, eht_su_beamformee, eht_mu_beamformer */
 	} else {
@@ -714,7 +728,7 @@
 #endif /* CONFIG_INTERWORKING */
 
 	std::string bridge_as_string;
-	if (!br_name.empty()) {
+	if (!br_name.empty() && !iface_params.usesMlo) {
 		bridge_as_string = StringPrintf("bridge=%s", br_name.c_str());
 	}
 
@@ -739,7 +753,7 @@
 	return StringPrintf(
 		"interface=%s\n"
 		"driver=nl80211\n"
-		"ctrl_interface=/data/vendor/wifi/hostapd/ctrl\n"
+		"ctrl_interface=/data/vendor/wifi/hostapd/ctrl_%s\n"
 		// ssid2 signals to hostapd that the value is not a literal value
 		// for use as a SSID.  In this case, we're giving it a hex
 		// std::string and hostapd needs to expect that.
@@ -762,7 +776,9 @@
 		"%s\n"
 		"%s\n"
 		"%s\n",
-		iface_params.name.c_str(), ssid_as_string.c_str(),
+		iface_params.usesMlo ? br_name.c_str() : iface_params.name.c_str(),
+		iface_params.name.c_str(),
+		ssid_as_string.c_str(),
 		channel_config_as_string.c_str(),
 		iface_params.hwModeParams.enable80211N ? 1 : 0,
 		iface_params.hwModeParams.enable80211AC ? 1 : 0,
@@ -1011,35 +1027,58 @@
 	return vssid;
 }
 
+
+// Both of bridged dual APs and MLO AP will be treated as concurrenct APs.
+// -----------------------------------------
+//                  | br_name     |  instance#1 | instance#2 |
+// ___________________________________________________________
+// bridged dual APs | ap_br_wlanX |   wlan X    |   wlanY    |
+// ___________________________________________________________
+// MLO AP           | wlanX       |     0       |     1      |
+// ___________________________________________________________
+// Both will be added in br_interfaces_[$br_name] and use instance's name
+// to be iface_params_new.name to create single Access point.
 ::ndk::ScopedAStatus Hostapd::addConcurrentAccessPoints(
 	const IfaceParams& iface_params, const NetworkParams& nw_params)
 {
 	int channelParamsListSize = iface_params.channelParams.size();
 	// Get available interfaces in bridge
-	std::vector<std::string> managed_interfaces;
-	std::string br_name = StringPrintf(
-		"%s", iface_params.name.c_str());
-	if (!GetInterfacesInBridge(br_name, &managed_interfaces)) {
-		return createStatusWithMsg(HostapdStatusCode::FAILURE_UNKNOWN,
-			"Get interfaces in bridge failed.");
+	std::vector<std::string> managed_instances;
+	std::string br_name = StringPrintf("%s", iface_params.name.c_str());
+	if (iface_params.usesMlo) {
+		// MLO AP is using link id as instance.
+		for (std::size_t i = 0; i < iface_params.instanceIdentities->size(); i++) {
+			managed_instances.push_back(iface_params.instanceIdentities->at(i)->c_str());
+		}
+	} else {
+		if (!GetInterfacesInBridge(br_name, &managed_instances)) {
+			return createStatusWithMsg(HostapdStatusCode::FAILURE_UNKNOWN,
+					"Get interfaces in bridge failed.");
+		}
 	}
-	if (managed_interfaces.size() < channelParamsListSize) {
+	// Either bridged AP or MLO AP should have two instances.
+	if (managed_instances.size() < channelParamsListSize) {
 		return createStatusWithMsg(HostapdStatusCode::FAILURE_UNKNOWN,
-			"Available interfaces less than requested bands");
+				"Available interfaces less than requested bands");
+	}
+
+	if (iface_params.usesMlo
+				&& nw_params.encryptionType == EncryptionType::WPA3_OWE_TRANSITION) {
+		return createStatusWithMsg(HostapdStatusCode::FAILURE_UNKNOWN,
+				"Invalid encryptionType (OWE transition) for MLO SAP.");
 	}
 	// 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 = "";
+		iface_params_new.name = managed_instances[i];
 		if (nw_params.encryptionType == EncryptionType::WPA3_OWE_TRANSITION) {
 			if (i == 0 && i+1 < channelParamsListSize) {
-				owe_transition_ifname = managed_interfaces[i+1];
+				owe_transition_ifname = managed_instances[i+1];
 				nw_params_new.encryptionType = EncryptionType::NONE;
 			} else {
-				owe_transition_ifname = managed_interfaces[0];
+				owe_transition_ifname = managed_instances[0];
 				nw_params_new.isHidden = true;
 				nw_params_new.ssid = generateRandomOweSsid();
 			}
@@ -1050,15 +1089,61 @@
 		    br_name, owe_transition_ifname);
 		if (!status.isOk()) {
 			wpa_printf(MSG_ERROR, "Failed to addAccessPoint %s",
-				   managed_interfaces[i].c_str());
+				   managed_instances[i].c_str());
 			return status;
 		}
 	}
+
+	if (iface_params.usesMlo) {
+		std::size_t i = 0;
+		std::size_t j = 0;
+		for (i = 0; i < interfaces_->count; i++) {
+			struct hostapd_iface *iface = interfaces_->iface[i];
+
+			for (j = 0; j < iface->num_bss; j++) {
+				struct hostapd_data *iface_hapd = iface->bss[j];
+				if (hostapd_enable_iface(iface_hapd->iface) < 0) {
+					wpa_printf(
+					MSG_ERROR, "Enabling interface %s failed on %zu",
+						iface_params.name.c_str(), i);
+					return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
+				}
+			}
+		}
+    }
 	// Save bridge interface info
-	br_interfaces_[br_name] = managed_interfaces;
+	br_interfaces_[br_name] = managed_instances;
 	return ndk::ScopedAStatus::ok();
 }
 
+struct hostapd_data * hostapd_get_iface_by_link_id(struct hapd_interfaces *interfaces,
+					const size_t link_id)
+{
+#ifdef CONFIG_IEEE80211BE
+	size_t i, j;
+
+	for (i = 0; i < interfaces->count; i++) {
+		struct hostapd_iface *iface = interfaces->iface[i];
+
+		for (j = 0; j < iface->num_bss; j++) {
+			struct hostapd_data *hapd = iface->bss[j];
+
+			if (link_id == hapd->mld_link_id)
+				return hapd;
+		}
+	}
+#endif
+	return NULL;
+}
+
+// Both of bridged dual APs and MLO AP will be treated as concurrenct APs.
+// -----------------------------------------
+//                  | br_name                 |  iface_params.name
+// _______________________________________________________________
+// bridged dual APs | bridged interface name  |  interface name
+// _______________________________________________________________
+// MLO AP           | AP interface name       |  mld link id as instance name
+// _______________________________________________________________
 ::ndk::ScopedAStatus Hostapd::addSingleAccessPoint(
 	const IfaceParams& iface_params,
 	const ChannelParams& channelParams,
@@ -1066,10 +1151,19 @@
 	const std::string br_name,
 	const std::string owe_transition_ifname)
 {
-	if (hostapd_get_iface(interfaces_, iface_params.name.c_str())) {
+	if (iface_params.usesMlo) { // the mlo case, iface name is instance name which is mld_link_id
+		if (hostapd_get_iface_by_link_id(interfaces_, (size_t) iface_params.name.c_str())) {
+			wpa_printf(
+				MSG_ERROR, "Instance link id %s already present",
+				iface_params.name.c_str());
+			return createStatus(HostapdStatusCode::FAILURE_IFACE_EXISTS);
+		}
+	}
+	if (hostapd_get_iface(interfaces_,
+			iface_params.usesMlo ? br_name.c_str() : iface_params.name.c_str())) {
 		wpa_printf(
-			MSG_ERROR, "Interface %s already present",
-			iface_params.name.c_str());
+			MSG_ERROR, "Instance interface %s already present",
+			iface_params.usesMlo ? br_name.c_str() : iface_params.name.c_str());
 		return createStatus(HostapdStatusCode::FAILURE_IFACE_EXISTS);
 	}
 	const auto conf_params = CreateHostapdConfig(iface_params, channelParams, nw_params,
@@ -1079,26 +1173,46 @@
 		return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
 	}
 	const auto conf_file_path =
-		WriteHostapdConfig(iface_params.name, conf_params);
+		WriteHostapdConfig(iface_params.name, conf_params, br_name, iface_params.usesMlo);
 	if (conf_file_path.empty()) {
 		wpa_printf(MSG_ERROR, "Failed to write config file");
 		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
 	}
 	std::string add_iface_param_str = StringPrintf(
-		"%s config=%s", iface_params.name.c_str(),
+		"%s config=%s", iface_params.usesMlo ? br_name.c_str(): iface_params.name.c_str(),
 		conf_file_path.c_str());
 	std::vector<char> add_iface_param_vec(
 		add_iface_param_str.begin(), add_iface_param_str.end() + 1);
 	if (hostapd_add_iface(interfaces_, add_iface_param_vec.data()) < 0) {
 		wpa_printf(
-			MSG_ERROR, "Adding interface %s failed",
+			MSG_ERROR, "Adding hostapd iface %s failed",
 			add_iface_param_str.c_str());
 		return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
 	}
-	struct hostapd_data* iface_hapd =
-	    hostapd_get_iface(interfaces_, iface_params.name.c_str());
+
+	// find the iface and set up callback.
+	struct hostapd_data* iface_hapd = iface_params.usesMlo ?
+		hostapd_get_iface_by_link_id(interfaces_, (size_t) iface_params.name.c_str()) :
+		hostapd_get_iface(interfaces_, iface_params.name.c_str());
 	WPA_ASSERT(iface_hapd != nullptr && iface_hapd->iface != nullptr);
+	if (iface_params.usesMlo) {
+		memcmp(iface_hapd->conf->iface, br_name.c_str(), br_name.size());
+	}
+
+	// Callback discrepancy between bridged dual APs and MLO AP
+	// Note: Only bridged dual APs will have "iface_hapd->conf->bridge" and
+	// Only MLO AP will have "iface_hapd->mld_link_id"
 	// Register the setup complete callbacks
+	// -----------------------------------------
+	//                    |   bridged dual APs     | bridged single link MLO | MLO SAP
+	// _________________________________________________________________________________________
+	// hapd->conf->bridge | bridged interface name |  bridged interface nam  | N/A
+	// _________________________________________________________________________________________
+	// hapd->conf->iface  | AP interface name      |  AP interface name      | AP interface name
+	// _________________________________________________________________________________________
+	// hapd->mld_link_id  | 0 (default value)      |      link id (0)        | link id (0 or 1)
+	// _________________________________________________________________________________________
+	// hapd->mld_ap       |         0              |            1            |     1
 	on_setup_complete_internal_callback =
 		[this](struct hostapd_data* iface_hapd) {
 			wpa_printf(
@@ -1107,11 +1221,18 @@
 			if (iface_hapd->iface->state == HAPD_IFACE_DISABLED) {
 				// Invoke the failure callback on all registered
 				// clients.
+				std::string instanceName = iface_hapd->conf->iface;
+#ifdef CONFIG_IEEE80211BE
+				if (iface_hapd->conf->mld_ap
+						&& strlen(iface_hapd->conf->bridge) == 0) {
+					instanceName = std::to_string(iface_hapd->mld_link_id);
+				}
+#endif
 				for (const auto& callback : callbacks_) {
 					auto status = callback->onFailure(
 						strlen(iface_hapd->conf->bridge) > 0 ?
 						iface_hapd->conf->bridge : iface_hapd->conf->iface,
-							    iface_hapd->conf->iface);
+							    instanceName);
 					if (!status.isOk()) {
 						wpa_printf(MSG_ERROR, "Failed to invoke onFailure");
 					}
@@ -1129,7 +1250,14 @@
 		ClientInfo info;
 		info.ifaceName = strlen(iface_hapd->conf->bridge) > 0 ?
 			iface_hapd->conf->bridge : iface_hapd->conf->iface;
-		info.apIfaceInstance = iface_hapd->conf->iface;
+		std::string instanceName = iface_hapd->conf->iface;
+#ifdef CONFIG_IEEE80211BE
+		if (iface_hapd->conf->mld_ap
+				&& strlen(iface_hapd->conf->bridge) == 0) {
+			instanceName = std::to_string(iface_hapd->mld_link_id);
+		}
+#endif
+		info.apIfaceInstance = instanceName;
 		info.clientAddress.assign(mac_addr, mac_addr + ETH_ALEN);
 		info.isConnected = authorized;
 		for (const auto &callback : callbacks_) {
@@ -1150,10 +1278,16 @@
 					strlen(AP_EVENT_ENABLED)) == 0 ||
 			os_strncmp(txt, WPA_EVENT_CHANNEL_SWITCH,
 					strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
+			std::string instanceName = iface_hapd->conf->iface;
+#ifdef CONFIG_IEEE80211BE
+			if (iface_hapd->conf->mld_ap && strlen(iface_hapd->conf->bridge) == 0) {
+				instanceName = std::to_string(iface_hapd->mld_link_id);
+			}
+#endif
 			ApInfo info;
 			info.ifaceName = strlen(iface_hapd->conf->bridge) > 0 ?
 				iface_hapd->conf->bridge : iface_hapd->conf->iface,
-			info.apIfaceInstance = iface_hapd->conf->iface;
+			info.apIfaceInstance = instanceName;
 			info.freqMhz = iface_hapd->iface->freq;
 			info.channelBandwidth = getChannelBandwidth(iface_hapd->iconf);
 			info.generation = getGeneration(iface_hapd->iface->current_mode);
@@ -1169,11 +1303,18 @@
 		} else if (os_strncmp(txt, AP_EVENT_DISABLED, strlen(AP_EVENT_DISABLED)) == 0
                            || os_strncmp(txt, INTERFACE_DISABLED, strlen(INTERFACE_DISABLED)) == 0)
 		{
+			std::string instanceName = iface_hapd->conf->iface;
+#ifdef CONFIG_IEEE80211BE
+			if (iface_hapd->conf->mld_ap && strlen(iface_hapd->conf->bridge) == 0) {
+				instanceName = std::to_string(iface_hapd->mld_link_id);
+			}
+#endif
 			// Invoke the failure callback on all registered clients.
 			for (const auto& callback : callbacks_) {
-				auto status = callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
+				auto status =
+					callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
 					iface_hapd->conf->bridge : iface_hapd->conf->iface,
-						    iface_hapd->conf->iface);
+						instanceName);
 				if (!status.isOk()) {
 					wpa_printf(MSG_ERROR, "Failed to invoke onFailure");
 				}
@@ -1188,7 +1329,8 @@
 	iface_hapd->sta_authorized_cb_ctx = iface_hapd;
 	wpa_msg_register_aidl_cb(onAsyncWpaEventCb);
 
-	if (hostapd_enable_iface(iface_hapd->iface) < 0) {
+	// Multi-link MLO should enable iface after both links have been set.
+	if (!iface_params.usesMlo && hostapd_enable_iface(iface_hapd->iface) < 0) {
 		wpa_printf(
 			MSG_ERROR, "Enabling interface %s failed",
 			iface_params.name.c_str());
diff --git a/wpa_supplicant/Android.bp b/wpa_supplicant/Android.bp
index afcc04b..619e35a 100644
--- a/wpa_supplicant/Android.bp
+++ b/wpa_supplicant/Android.bp
@@ -67,7 +67,7 @@
     defaults: ["wpa_supplicant_cflags_defaults"],
     srcs: [":wpa_supplicant_srcs"],
     shared_libs: [
-        "android.hardware.wifi.supplicant-V3-ndk",
+        "android.hardware.wifi.supplicant-V4-ndk",
         "android.system.keystore2-V1-ndk",
         "libbase",
         "libbinder_ndk",
@@ -129,7 +129,6 @@
         "-DCONFIG_NO_RADIUS",
         "-DCONFIG_NO_RADIUS",
         "-DCONFIG_NO_RANDOM_POOL",
-        "-DCONFIG_NO_ROAMING",
         "-DCONFIG_NO_VLAN",
         "-DCONFIG_OFFCHANNEL",
         "-DCONFIG_OWE",
@@ -161,6 +160,7 @@
         "-DEAP_MSCHAPv2",
         "-DEAP_OTP",
         "-DEAP_PEAP",
+        "-DCONFIG_PTKSA_CACHE",
         "-DEAP_PWD",
         "-DEAP_SERVER",
         "-DEAP_SERVER_IDENTITY",
@@ -199,6 +199,21 @@
             any @ driver: ["-D" + driver],
             // Flag is optional, so no default value provided.
             default: [],
+        }) +
+        select(soong_config_variable("wpa_supplicant", "roaming"), {
+            true: [],
+            default: ["-DCONFIG_NO_ROAMING"],
+        }) +
+        select(soong_config_variable("wpa_supplicant", "pasn"), {
+            false: [],
+            default: ["-DCONFIG_PASN"],
+        }) +
+        select(soong_config_variable("wpa_supplicant", "bgscan_simple"), {
+            true: [
+                "-DCONFIG_BGSCAN",
+                "-DCONFIG_BGSCAN_SIMPLE",
+            ],
+            default: [],
         }),
     // Similar to suppressing clang compiler warnings, here we
     // suppress clang-tidy warnings to reduce noises in Android build.log.
@@ -264,7 +279,6 @@
         "src/ap/ap_drv_ops.c",
         "src/ap/ap_list.c",
         "src/ap/comeback_token.c",
-        "src/pasn/pasn_responder.c",
         "src/ap/ap_mlme.c",
         "src/ap/authsrv.c",
         "src/ap/beacon.c",
@@ -432,7 +446,24 @@
         "wpas_glue.c",
         "wpa_supplicant.c",
         "wps_supplicant.c",
-    ],
+    ] +
+        select(soong_config_variable("wpa_supplicant", "bgscan_simple"), {
+            true: [
+                "bgscan.c",
+                "bgscan_simple.c",
+            ],
+            default: [],
+        }) +
+        select(soong_config_variable("wpa_supplicant", "pasn"), {
+            false: [],
+            default: [
+                "pasn_supplicant.c",
+                "src/pasn/pasn_initiator.c",
+                "src/pasn/pasn_responder.c",
+                "src/pasn/pasn_common.c",
+            ],
+        }),
+
 }
 
 // Generated by building wpa_cli and printing LOCAL_SRC_FILES
@@ -467,3 +498,181 @@
     ],
     soc_specific: true,
 }
+
+cc_library {
+    name: "libpasn",
+    vendor: true,
+    cflags: [
+        "-DANDROID_LOG_NAME=\"libpasn\"",
+        "-DANDROID_P2P",
+        "-DCONFIG_ACS",
+        "-DCONFIG_ANDROID_LOG",
+        "-DCONFIG_AP",
+        "-DCONFIG_BACKEND_FILE",
+        "-DCONFIG_CTRL_IFACE",
+        "-DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/vendor/wifi/wpa/sockets\"",
+        "-DCONFIG_CTRL_IFACE_DIR=\"/data/vendor/wifi/wpa/sockets\"",
+        "-DCONFIG_CTRL_IFACE_AIDL",
+        "-DCONFIG_CTRL_IFACE_UNIX",
+        "-DCONFIG_DPP",
+        "-DCONFIG_DPP2",
+        "-DCONFIG_DRIVER_NL80211",
+        "-DCONFIG_ECC",
+        "-DCONFIG_ERP",
+        "-DCONFIG_FILS",
+        "-DCONFIG_GAS",
+        "-DCONFIG_GAS_SERVER",
+        "-DCONFIG_AIDL",
+        "-DCONFIG_HMAC_SHA256_KDF",
+        "-DCONFIG_HMAC_SHA384_KDF",
+        "-DCONFIG_HMAC_SHA512_KDF",
+        "-DCONFIG_HS20",
+        "-DCONFIG_IEEE80211AC",
+        "-DCONFIG_IEEE80211R",
+        "-DCONFIG_INTERWORKING",
+        "-DCONFIG_IPV6",
+        "-DCONFIG_JSON",
+        "-DCONFIG_MBO",
+        "-DCONFIG_NO_ACCOUNTING",
+        "-DCONFIG_NO_RADIUS",
+        "-DCONFIG_NO_RADIUS",
+        "-DCONFIG_NO_RANDOM_POOL",
+        "-DCONFIG_NO_ROAMING",
+        "-DCONFIG_NO_VLAN",
+        "-DCONFIG_OFFCHANNEL",
+        "-DCONFIG_OWE",
+        "-DCONFIG_P2P",
+        "-DCONFIG_SAE",
+        "-DCONFIG_SAE_PK",
+        "-DCONFIG_SHA256",
+        "-DCONFIG_SHA384",
+        "-DCONFIG_SHA512",
+        "-DCONFIG_SMARTCARD",
+        "-DCONFIG_SME",
+        "-DCONFIG_SUITEB",
+        "-DCONFIG_SUITEB192",
+        "-DCONFIG_TDLS",
+        "-DCONFIG_WEP",
+        "-DCONFIG_WIFI_DISPLAY",
+        "-DCONFIG_WNM",
+        "-DCONFIG_WPA_CLI_HISTORY_DIR=\"/data/vendor/wifi/wpa\"",
+        "-DCONFIG_WPS",
+        "-DCONFIG_WPS_ER",
+        "-DCONFIG_WPS_NFC",
+        "-DCONFIG_WPS_OOB",
+        "-DCONFIG_WPS_UPNP",
+        "-DEAP_AKA",
+        "-DEAP_AKA_PRIME",
+        "-DEAP_GTC",
+        "-DEAP_LEAP",
+        "-DEAP_MD5",
+        "-DEAP_MSCHAPv2",
+        "-DEAP_OTP",
+        "-DEAP_PEAP",
+        "-DCONFIG_PASN",
+        "-DCONFIG_PTKSA_CACHE",
+        "-DEAP_PWD",
+        "-DEAP_SERVER",
+        "-DEAP_SERVER_IDENTITY",
+        "-DEAP_SERVER_WSC",
+        "-DEAP_SIM",
+        "-DEAP_TLS",
+        "-DEAP_TLS_OPENSSL",
+        "-DEAP_TTLS",
+        "-DEAP_WSC",
+        "-DIEEE8021X_EAPOL",
+        "-DNEED_AP_MLME",
+        "-DPKCS12_FUNCS",
+        "-DTLS_DEFAULT_CIPHERS=\"DEFAULT:!EXP:!LOW\"",
+        "-DWPA_IGNORE_CONFIG_ERRORS",
+        "-Wall",
+        "-Werror",
+        "-Wno-error=sometimes-uninitialized",
+        "-Wno-incompatible-pointer-types",
+        "-Wno-incompatible-pointer-types-discards-qualifiers",
+        "-Wno-macro-redefined",
+        "-Wno-parentheses-equality",
+        "-Wno-sign-compare",
+        "-Wno-unused-function",
+        "-Wno-unused-parameter",
+        "-Wno-unused-variable",
+    ],
+    product_variables: {
+        debuggable: {
+            cflags: ["-DLOG_NDEBUG=0"],
+        },
+    },
+    local_include_dirs: [
+        ".",
+        "src",
+        "src/common",
+        "src/drivers",
+        "src/eap_common",
+        "src/eapol_supp",
+        "src/eap_peer",
+        "src/eap_server",
+        "src/l2_packet",
+        "src/radius",
+        "src/rsn_supp",
+        "src/tls",
+        "src/utils",
+        "src/wps",
+    ],
+    srcs: [
+        "src/utils/eloop.c",
+        "src/utils/wpa_debug.c",
+        "src/utils/wpabuf.c",
+        "src/utils/os_unix.c",
+        "src/utils/config.c",
+        "src/utils/common.c",
+        "src/utils/base64.c",
+        "src/common/sae.c",
+        "src/common/sae_pk.c",
+        "src/common/wpa_common.c",
+        "src/common/ieee802_11_common.c",
+        "src/common/dragonfly.c",
+        "src/common/ptksa_cache.c",
+        "src/rsn_supp/pmksa_cache.c",
+        "src/rsn_supp/wpa_ie.c",
+        "src/ap/comeback_token.c",
+        "src/ap/pmksa_cache_auth.c",
+        "src/eap_common/eap_common.c",
+        "src/eap_common/chap.c",
+        "src/eap_peer/eap.c",
+        "src/eap_peer/eap_methods.c",
+        "src/eapol_supp/eapol_supp_sm.c",
+        "src/crypto/crypto_openssl.c",
+        "src/crypto/tls_openssl.c",
+        "src/crypto/tls_openssl_ocsp.c",
+        "src/crypto/sha256-tlsprf.c",
+        "src/crypto/sha512-prf.c",
+        "src/crypto/sha384-prf.c",
+        "src/crypto/sha256-prf.c",
+        "src/crypto/sha512-kdf.c",
+        "src/crypto/sha384-kdf.c",
+        "src/crypto/sha256-kdf.c",
+        "src/crypto/dh_groups.c",
+        "src/crypto/aes-siv.c",
+        "src/crypto/aes-ctr.c",
+        "src/crypto/sha1-prf.c",
+        "src/crypto/sha1-tlsprf.c",
+        "src/pasn/pasn_initiator.c",
+        "src/pasn/pasn_responder.c",
+        "src/pasn/pasn_common.c",
+    ],
+    shared_libs: [
+        "libc",
+        "libcutils",
+        "liblog",
+        "libcrypto",
+        "libssl",
+        "libkeystore-engine-wifi-hidl",
+    ],
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index b667d82..581d907 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -18,7 +18,11 @@
   CONFIG_DRIVER_NL80211_QCA=y
 endif
 
-include $(LOCAL_PATH)/android.config
+ifneq ($(SUPPLICANT_CUSTOM_DEF_CONFIG_FILE_PATH),)
+  include $(SUPPLICANT_CUSTOM_DEF_CONFIG_FILE_PATH)
+else
+  include $(LOCAL_PATH)/android.config
+endif
 
 # To ignore possible wrong network configurations
 L_CFLAGS = -DWPA_IGNORE_CONFIG_ERRORS
@@ -2002,7 +2006,7 @@
 LOCAL_MODULE := wpa_supplicant
 
 ifeq ($(WPA_SUPPLICANT_USE_AIDL), y)
-LOCAL_SHARED_LIBRARIES += android.hardware.wifi.supplicant-V3-ndk
+LOCAL_SHARED_LIBRARIES += android.hardware.wifi.supplicant-V4-ndk
 LOCAL_SHARED_LIBRARIES += android.system.keystore2-V1-ndk
 LOCAL_SHARED_LIBRARIES += libutils libbase
 LOCAL_SHARED_LIBRARIES += libbinder_ndk
@@ -2106,7 +2110,7 @@
     aidl/sta_network.cpp \
     aidl/supplicant.cpp
 LOCAL_SHARED_LIBRARIES := \
-    android.hardware.wifi.supplicant-V3-ndk \
+    android.hardware.wifi.supplicant-V4-ndk \
     android.system.keystore2-V1-ndk \
     libbinder_ndk \
     libbase \
@@ -2117,21 +2121,3 @@
     $(LOCAL_PATH)/aidl
 include $(BUILD_STATIC_LIBRARY)
 endif # WPA_SUPPLICANT_USE_AIDL == y
-
-ifeq ($(CONFIG_PASN), y)
-include $(CLEAR_VARS)
-LOCAL_MODULE = libpasn
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-BSD SPDX-license-identifier-BSD-3-Clause SPDX-license-identifier-ISC legacy_unencumbered
-LOCAL_LICENSE_CONDITIONS := notice unencumbered
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../LICENSE
-LOCAL_VENDOR_MODULE := true
-LOCAL_CFLAGS = $(L_CFLAGS)
-LOCAL_SRC_FILES = $(PASNOBJS)
-LOCAL_C_INCLUDES = $(INCLUDES)
-LOCAL_SHARED_LIBRARIES := libc libcutils liblog
-ifeq ($(CONFIG_TLS), openssl)
-LOCAL_SHARED_LIBRARIES += libcrypto libssl libkeystore-wifi-hidl
-LOCAL_SHARED_LIBRARIES += libkeystore-engine-wifi-hidl
-endif
-include $(BUILD_SHARED_LIBRARY)
-endif # CONFIG_PASN == y
diff --git a/wpa_supplicant/aidl/Android.bp b/wpa_supplicant/aidl/Android.bp
index d523630..5976ff9 100644
--- a/wpa_supplicant/aidl/Android.bp
+++ b/wpa_supplicant/aidl/Android.bp
@@ -36,7 +36,7 @@
     ],
     soc_specific: true,
     shared_libs: [
-        "android.hardware.wifi.supplicant-V3-ndk",
+        "android.hardware.wifi.supplicant-V4-ndk",
         "android.system.keystore2-V1-ndk",
         "libbinder_ndk",
         "libbase",
@@ -83,3 +83,10 @@
         },
     },
 }
+
+prebuilt_etc {
+    name: "android.hardware.wifi.supplicant.xml.prebuilt",
+    src: "android.hardware.wifi.supplicant.xml",
+    relative_install_path: "vintf",
+    installable: false,
+}
diff --git a/wpa_supplicant/aidl/aidl_manager.cpp b/wpa_supplicant/aidl/aidl_manager.cpp
index 4c50449..db9ece4 100644
--- a/wpa_supplicant/aidl/aidl_manager.cpp
+++ b/wpa_supplicant/aidl/aidl_manager.cpp
@@ -1529,6 +1529,10 @@
 			   params.p2pClientIpInfo.ipAddressMask,
 			   params.p2pClientIpInfo.ipAddressGo);
         }
+	if (isAidlServiceVersionAtLeast(4)) {
+		// TODO Fill the field when supplicant implementation is ready
+		params.keyMgmtMask = 0;
+	}
 	callWithEachP2pIfaceCallback(
 		misc_utils::charBufToString(wpa_s->ifname),
 		std::bind(&ISupplicantP2pIfaceCallback::onGroupStartedWithParams,
@@ -1686,6 +1690,10 @@
 			os_memcpy(&aidl_ip, &ip[0], 4);
 		}
 		params.clientIpAddress = aidl_ip;
+		if (isAidlServiceVersionAtLeast(4)) {
+			// TODO Fill the field when supplicant implementation is ready
+			params.keyMgmtMask = 0;
+		}
 		callWithEachP2pIfaceCallback(
 			misc_utils::charBufToString(wpa_s->ifname),
 			std::bind(
diff --git a/wpa_supplicant/aidl/android.hardware.wifi.supplicant.xml b/wpa_supplicant/aidl/android.hardware.wifi.supplicant.xml
index 37cc3af..103d37f 100644
--- a/wpa_supplicant/aidl/android.hardware.wifi.supplicant.xml
+++ b/wpa_supplicant/aidl/android.hardware.wifi.supplicant.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
 	<hal format="aidl">
 		<name>android.hardware.wifi.supplicant</name>
-		<version>3</version>
+		<version>4</version>
 		<fqname>ISupplicant/default</fqname>
 	</hal>
 </manifest>
diff --git a/wpa_supplicant/aidl/p2p_iface.cpp b/wpa_supplicant/aidl/p2p_iface.cpp
index 2005af2..e6610de 100644
--- a/wpa_supplicant/aidl/p2p_iface.cpp
+++ b/wpa_supplicant/aidl/p2p_iface.cpp
@@ -853,6 +853,14 @@
 		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
 		&P2pIface::createGroupOwnerInternal, in_groupOwnerInfo);
 }
+
+::ndk::ScopedAStatus P2pIface::getFeatureSet(int64_t* _aidl_return)
+{
+	return validateAndCall(
+		this, SupplicantStatusCode::FAILURE_UNKNOWN,
+		&P2pIface::getFeatureSetInternal, _aidl_return);
+}
+
 std::pair<std::string, ndk::ScopedAStatus> P2pIface::getNameInternal()
 {
 	return {ifname_, ndk::ScopedAStatus::ok()};
@@ -1944,6 +1952,12 @@
 		groupOwnerInfo.persistent, groupOwnerInfo.persistentNetworkId);
 }
 
+std::pair<int64_t, ndk::ScopedAStatus> P2pIface::getFeatureSetInternal()
+{
+	// TODO Fill the field when supplicant implementation is ready
+	return {0, 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 98556d1..4f7ae0a 100644
--- a/wpa_supplicant/aidl/p2p_iface.h
+++ b/wpa_supplicant/aidl/p2p_iface.h
@@ -184,6 +184,7 @@
 		const P2pAddGroupConfigurationParams& in_groupConfigurationParams) override;
 	::ndk::ScopedAStatus createGroupOwner(
 		const P2pCreateGroupOwnerInfo& in_groupOwnerInfo) override;
+	::ndk::ScopedAStatus getFeatureSet(int64_t* _aidl_return) override;
 
 
 private:
@@ -316,6 +317,7 @@
 		const P2pAddGroupConfigurationParams& groupConfigurationParams);
 	ndk::ScopedAStatus createGroupOwnerInternal(
 		const P2pCreateGroupOwnerInfo& groupOwnerInfo);
+	std::pair<int64_t, ndk::ScopedAStatus> getFeatureSetInternal();
 
 	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 a4c2c36..3880a1d 100644
--- a/wpa_supplicant/aidl/sta_iface.cpp
+++ b/wpa_supplicant/aidl/sta_iface.cpp
@@ -1920,6 +1920,11 @@
 #ifdef EAP_TLSV1_3
 	mask |= static_cast<uint32_t>(WpaDriverCapabilitiesMask::TLS_V1_3);
 #endif
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	WPA_ASSERT(aidl_manager);
+	if (aidl_manager->isAidlServiceVersionAtLeast(4) && wpas_rsn_overriding(wpa_s)) {
+		mask |= static_cast<uint32_t>(WpaDriverCapabilitiesMask::RSN_OVERRIDING);
+	}
 
 	wpa_printf(MSG_DEBUG, "Driver capability mask: 0x%x", mask);